ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dpav...@apache.org
Subject [ignite-teamcity-bot] branch master updated: IGNITE-11853: Links fixed for tests failures, trusted suites development, filtering old issues, filtering disabled issues, possible blockers simplified. (#124)
Date Thu, 16 May 2019 18:37:23 GMT
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 472e1dd  IGNITE-11853: Links fixed for tests failures, trusted suites development, filtering old issues, filtering disabled issues, possible blockers simplified. (#124)
472e1dd is described below

commit 472e1dd308130a11948c6b3478b65cf5239d01f8
Author: Dmitriy Pavlov <dpavlov@apache.org>
AuthorDate: Thu May 16 21:37:19 2019 +0300

    IGNITE-11853: Links fixed for tests failures, trusted suites development, filtering old issues, filtering disabled issues, possible blockers simplified. (#124)
---
 conf/branches.json                                 |  20 ++-
 .../ignite/ci/analysis/IMultTestOccurrence.java    |   3 +
 .../apache/ignite/ci/analysis/ISuiteResults.java   |  21 ++-
 .../apache/ignite/ci/analysis/MultBuildRunCtx.java | 120 +++++++++++++++-
 .../ignite/ci/analysis/SingleBuildRunCtx.java      |   4 +
 .../ignite/ci/analysis/TestCompactedMult.java      |  18 +++
 .../java/org/apache/ignite/ci/issue/Issue.java     |   9 +-
 .../java/org/apache/ignite/ci/issue/IssueType.java |  31 ++++-
 .../ignite/ci/tcbot/chain/PrChainsProcessor.java   | 115 ++++++++--------
 .../tcbot/chain/TrackedBranchChainsProcessor.java  |  11 +-
 .../apache/ignite/ci/tcbot/conf/BranchTracked.java |  17 +++
 .../ignite/ci/tcbot/conf/ITcServerConfig.java      |  13 +-
 .../ignite/ci/tcbot/conf/TcServerConfig.java       |  11 ++
 .../ignite/ci/tcbot/issue/IssueDetector.java       |  80 ++++++++---
 .../ignite/ci/tcbot/visa/CurrentVisaStatus.java    |   1 +
 .../tcbot/visa/TcBotTriggerAndSignOffService.java  |  50 ++++---
 .../teamcity/ignited/ITeamcityIgnitedProvider.java |   2 +-
 .../ignited/fatbuild/ProblemCompacted.java         |   4 +
 .../ci/teamcity/ignited/runhist/RunHistSync.java   |   2 +-
 .../model/current/ChainAtServerCurrentStatus.java  |  21 ++-
 .../ci/web/model/current/SuiteCurrentStatus.java   | 153 ++++++++++++---------
 .../ignite/ci/web/model/current/TestFailure.java   |  36 +++--
 .../ignite/ci/web/rest/GetChainResultsAsHtml.java  |   3 +-
 .../ci/web/rest/build/GetBuildTestFailures.java    |   3 +-
 .../rest/tracked/GetTrackedBranchTestResults.java  |   1 -
 ignite-tc-helper-web/src/main/webapp/all.html      |   4 +-
 .../src/main/webapp/build-comparator.html          |   4 +-
 ignite-tc-helper-web/src/main/webapp/build.html    |   4 +-
 ignite-tc-helper-web/src/main/webapp/current.html  |   4 +-
 .../js/{testfails-2.1.js => testfails-2.2.js}      | 126 +++++------------
 .../src/main/webapp/monitoring.html                |   2 +-
 ignite-tc-helper-web/src/main/webapp/pr.html       |   4 +-
 ignite-tc-helper-web/src/main/webapp/prs.html      |   2 +-
 .../ci/tcbot/chain/PrChainsProcessorTest.java      |  14 --
 .../ignited/IgnitedTcInMemoryIntegrationTest.java  |   1 +
 .../ci/teamcity/ignited/TeamcityIgnitedMock.java   |   5 +
 36 files changed, 588 insertions(+), 331 deletions(-)

diff --git a/conf/branches.json b/conf/branches.json
index 5be6ae2..e42a53a 100644
--- a/conf/branches.json
+++ b/conf/branches.json
@@ -30,7 +30,9 @@
             {"value":"%env.JDK_OPEN_11%", "label":"JDK11"}
           ]
         }
-      ]
+      ],
+      /** Build type IDs, which should trigger notifications about any non build problem, and should be blocker in this case. **/
+      "trustedSuites": []
     }
   ],
   /* Set of JIRA servers/projects configured */
@@ -102,7 +104,9 @@
           "suiteId": "IgniteTests24Java8_RunAll",
           "branchForRest": "\u003cdefault\u003e"
         }
-      ]
+      ],
+      /* Disable notifications for the following issue types. See {@link IssueType#code()}. */
+      "disableIssueTypes": []
     },
     {
       "id": "master-nightly",
@@ -128,7 +132,9 @@
             }
           ]
         }
-      ]
+      ],
+      /* Disable notifications for the following issue types. See {@link IssueType#code()}. */
+      "disableIssueTypes": []
     },
     {
       "id": "ignite-2.7.5",
@@ -139,7 +145,9 @@
           "branchForRest": "ignite-2.7.5",
           "baseBranchForTc": "\u003cdefault\u003e"
         }
-      ]
+      ],
+      /* Disable notifications for the following issue types. See {@link IssueType#code()}. */
+      "disableIssueTypes": []
     },
     {
       "id": "ignite-2.7.5-nightly",
@@ -152,7 +160,9 @@
           "triggerBuild": true,
           "triggerBuildQuietPeriod": 30 //triggering quiet period in minutes
         }
-      ]
+      ],
+      /* Disable notifications for the following issue types. See {@link IssueType#code()}. */
+      "disableIssueTypes": []
     }
   ]
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/IMultTestOccurrence.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/IMultTestOccurrence.java
index 4ae72ac..0a16487 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/IMultTestOccurrence.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/IMultTestOccurrence.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.ci.analysis;
 
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrenceFull;
+import org.apache.ignite.ci.teamcity.ignited.IRunHistory;
 
 /**
  * Multiple test occurrence. For single build context - max 1 failure
@@ -32,4 +33,6 @@ public interface IMultTestOccurrence {
     public long getAvgDurationMs();
 
     Iterable<TestOccurrenceFull> getOccurrences();
+
+    String getPossibleBlockerComment(IRunHistory baseBranchStat);
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/ISuiteResults.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/ISuiteResults.java
index 3f41f4b..b4b49b7 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/ISuiteResults.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/ISuiteResults.java
@@ -22,18 +22,25 @@ package org.apache.ignite.ci.analysis;
  */
 public interface ISuiteResults {
     /** */
-    boolean hasCompilationProblem();
+    public boolean hasCompilationProblem();
 
     /** */
-    boolean hasMetricProblem();
+    public boolean hasMetricProblem();
 
-    boolean hasTimeoutProblem();
+    /** */
+    public boolean hasTimeoutProblem();
+
+    /** */
+    public boolean hasJvmCrashProblem();
 
-    boolean hasJvmCrashProblem();
+    /** */
+    public boolean hasOomeProblem();
 
-    boolean hasOomeProblem();
+    /** */
+    public boolean hasExitCodeProblem();
 
-    boolean hasExitCodeProblem();
+    /** */
+    public boolean hasBuildMessageProblem();
 
     default boolean hasCriticalProblem() {
         return hasJvmCrashProblem()
@@ -51,5 +58,5 @@ public interface ISuiteResults {
             || hasMetricProblem();
     }
 
-    String suiteId();
+    public String suiteId();
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java
index cd56ec5..da9af4e 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java
@@ -32,9 +32,11 @@ import java.util.concurrent.Future;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import javax.annotation.Nonnull;
+import org.apache.ignite.ci.tcbot.conf.ITcServerConfig;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
 import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
+import org.apache.ignite.ci.teamcity.ignited.IRunHistory;
 import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.change.ChangeCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.ProblemCompacted;
@@ -94,6 +96,11 @@ public class MultBuildRunCtx implements ISuiteResults {
         return firstBuildInfo.suiteId();
     }
 
+    /** {@inheritDoc} */
+    @Override public boolean hasBuildMessageProblem() {
+        return getBuildMessageProblemCount() > 0;
+    }
+
     public String buildTypeId() {
         return firstBuildInfo.buildTypeId;
     }
@@ -107,8 +114,7 @@ public class MultBuildRunCtx implements ISuiteResults {
         return buildsStream().allMatch(bCtx -> !bCtx.isComposite() && bCtx.isCancelled());
     }
 
-    @NotNull
-    private Stream<ProblemCompacted> allProblemsInAllBuilds() {
+    @NotNull public Stream<ProblemCompacted> allProblemsInAllBuilds() {
         return buildsStream().flatMap(SingleBuildRunCtx::getProblemsStream);
     }
 
@@ -126,6 +132,11 @@ public class MultBuildRunCtx implements ISuiteResults {
         return buildsStream().filter(ISuiteResults::hasMetricProblem).count();
     }
 
+    /** */
+    public long getBuildMessageProblemCount() {
+        return buildsStream().filter(ISuiteResults::hasBuildMessageProblem).count();
+    }
+
     /** {@inheritDoc} */
     @Override public boolean hasCompilationProblem() {
         return getCompilationProblemCount() > 0;
@@ -184,7 +195,7 @@ public class MultBuildRunCtx implements ISuiteResults {
     public String getResult() {
         StringBuilder res = new StringBuilder();
 
-        long cancelledCnt = buildsStream().filter(bCtx -> !bCtx.isComposite() && bCtx.isCancelled()).count();
+        long cancelledCnt = getCancelledBuildsCount();
 
         if (cancelledCnt > 0) {
             res.append(CANCELLED);
@@ -221,15 +232,21 @@ public class MultBuildRunCtx implements ISuiteResults {
             }
         }
 
+        addKnownProblemCnt(res, ProblemOccurrence.JAVA_LEVEL_DEADLOCK, getJavaLevelDeadlocksCount());
+
+        return res.toString();
+    }
+
+    public long getJavaLevelDeadlocksCount() {
         List<LogCheckResult> collect = getLogChecksIfFinished().collect(Collectors.toList());
 
-        long javaDeadlocks = collect.stream().map(LogCheckResult::getCustomProblems)
+        return collect.stream().map(LogCheckResult::getCustomProblems)
             .filter(set -> set.contains(ProblemOccurrence.JAVA_LEVEL_DEADLOCK))
             .count();
+    }
 
-        addKnownProblemCnt(res, ProblemOccurrence.JAVA_LEVEL_DEADLOCK, javaDeadlocks);
-
-        return res.toString();
+    public long getCancelledBuildsCount() {
+        return buildsStream().filter(bCtx -> !bCtx.isComposite() && bCtx.isCancelled()).count();
     }
 
     public void addKnownProblemCnt(StringBuilder res, String nme, long execToCnt) {
@@ -461,4 +478,93 @@ public class MultBuildRunCtx implements ISuiteResults {
     public Set<String> tags() {
         return buildsStream().flatMap(b -> b.tags().stream()).collect(Collectors.toSet());
     }
+
+    /**
+     * Classify suite if it is blossible blocker or not.
+     * @param compactor Compactor.
+     * @param baseBranchHist Base branch history for suite.
+     * @param tcSrvCfg
+     */
+    @NotNull public String getPossibleBlockerComment(@Nonnull IStringCompactor compactor,
+        @Nullable IRunHistory baseBranchHist,
+        @Nonnull ITcServerConfig tcSrvCfg) {
+        StringBuilder res = new StringBuilder();
+
+        long cancelledCnt = getCancelledBuildsCount();
+
+        if (cancelledCnt > 0) {
+            res.append("Suite was cancelled, cancellation is always a blocker ");
+
+            if (cancelledCnt > 1)
+                res.append(" [").append(cancelledCnt).append("] \n");
+        }
+
+        addKnownProblemAsPossibleBlocker(res, "Timeout", getExecutionTimeoutCount(), baseBranchHist, true);
+        addKnownProblemAsPossibleBlocker(res, "Jvm Crash", getJvmCrashProblemCount(), baseBranchHist, true);
+        addKnownProblemAsPossibleBlocker(res, "Failure on metric", getMetricProblemCount(), baseBranchHist, true);
+        addKnownProblemAsPossibleBlocker(res, "Compilation Error", getCompilationProblemCount(), baseBranchHist, true);
+
+        addKnownProblemAsPossibleBlocker(res, "Out Of Memory Error", getBuildMessageProblemCount(), baseBranchHist, false);
+        addKnownProblemAsPossibleBlocker(res, "Out Of Memory Error", getOomeProblemCount(), baseBranchHist, false);
+        addKnownProblemAsPossibleBlocker(res, "Exit Code", getExitCodeProblemsCount(), baseBranchHist, false);
+
+        if(hasAnyBuildProblemExceptTestOrSnapshot() && tcSrvCfg.trustedSuites().contains(suiteId())) {
+            res.append("Suite is trusted but has build problems");
+
+            res.append("[");
+            res.append(allProblemsInAllBuilds()
+                .filter(p -> !p.isFailedTests(compactor) && !p.isSnapshotDepProblem(compactor))
+                .map(p -> p.type(compactor)).distinct().collect(Collectors.joining(", ")));
+            res.append("] ");
+
+            appendFailRate(baseBranchHist, res).append(" \n");
+        }
+
+        long jldl = getJavaLevelDeadlocksCount();
+        if (jldl > 0) {
+            res.append("Java Level Deadlock detected, it is unconditional blocker")
+                .append(" ")
+                .append(jldl > 1 ? "[" + jldl + "]" : "")
+                .append(" \n");
+        }
+
+        return res.toString();
+    }
+
+    public void addKnownProblemAsPossibleBlocker(StringBuilder res, String nme, long execToCnt,
+        @Nullable IRunHistory baseBranchHist, boolean critical) {
+        if (execToCnt <= 0)
+            return;
+
+        res.append(nme).append(" is a blocker. ");
+
+        if (critical)
+            appendCriticalFailRate(baseBranchHist, res);
+        else
+            appendFailRate(baseBranchHist, res);
+
+        res.append(execToCnt > 1 ? "[" + execToCnt + "]" : "").append(" \n");
+    }
+
+    public StringBuilder appendFailRate(IRunHistory baseBranchHist, StringBuilder res) {
+        if (baseBranchHist == null)
+            return res;
+
+        res.append("Base branch fail rate is ");
+        res.append(baseBranchHist.getFailPercentPrintable());
+        res.append("% ");
+
+        return res;
+    }
+
+    public StringBuilder appendCriticalFailRate(IRunHistory baseBranchHist, StringBuilder res) {
+        if (baseBranchHist == null)
+            return res;
+
+        res.append("Base branch critical fail rate is ");
+        res.append(baseBranchHist.getCriticalFailPercentPrintable());
+        res.append("% ");
+
+        return res;
+    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/SingleBuildRunCtx.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/SingleBuildRunCtx.java
index 5433d4b..80dbdbe 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/SingleBuildRunCtx.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/SingleBuildRunCtx.java
@@ -119,6 +119,10 @@ public class SingleBuildRunCtx implements ISuiteResults {
         return compactor.getStringFromId(buildCompacted.buildTypeId());
     }
 
+    @Override public boolean hasBuildMessageProblem() {
+        return getProblemsStream().anyMatch(p -> p.isBuildFailureOnMessage(compactor));
+    }
+
     public void setLogCheckResFut(CompletableFuture<LogCheckResult> logCheckResFut) {
         this.logCheckResFut = logCheckResFut;
     }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/TestCompactedMult.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/TestCompactedMult.java
index 98a3604..409d948 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/TestCompactedMult.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/TestCompactedMult.java
@@ -22,6 +22,7 @@ import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrenceFull;
+import org.apache.ignite.ci.teamcity.ignited.IRunHistory;
 import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.TestCompacted;
 
@@ -77,6 +78,23 @@ public class TestCompactedMult implements IMultTestOccurrence {
             .collect(Collectors.toList());
     }
 
+    @Override public String getPossibleBlockerComment(IRunHistory baseBranchStat) {
+        if (baseBranchStat == null)
+            return "History for base branch is absent.";
+
+        String flakyComments = baseBranchStat.getFlakyComments();
+
+        boolean lowFailureRate = baseBranchStat.getFailRate() * 100.0f < 4.;
+
+        if (lowFailureRate && flakyComments == null) {
+            return "Test has low fail rate in base branch "
+                + baseBranchStat.getFailPercentPrintable()
+                + "% and is not flaky";
+        }
+
+        return null;
+    }
+
     public void add(TestCompacted next) {
         occurrences.add(next);
     }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/issue/Issue.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/issue/Issue.java
index 2c492d2..edddad8 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/issue/Issue.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/issue/Issue.java
@@ -33,7 +33,7 @@ import org.jetbrains.annotations.Nullable;
 @SuppressWarnings("WeakerAccess")
 @Persisted
 public class Issue {
-    /** Type. Null of older versions of issue */
+    /** Type code. Null of older versions of issue */
     @Nullable
     private String type;
 
@@ -55,7 +55,10 @@ public class Issue {
     @Nullable
     public String displayName;
 
+    /** Build start timestamp. */
     @Nullable public Long buildStartTs;
+
+    /** Detected timestamp. */
     @Nullable public Long detectedTs;
 
     public Issue(IssueKey issueKey, IssueType type) {
@@ -209,4 +212,8 @@ public class Issue {
 
         return sb.toString();
     }
+
+    public String type() {
+        return type;
+    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/issue/IssueType.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/issue/IssueType.java
index 59fcb75..a690614 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/issue/IssueType.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/issue/IssueType.java
@@ -17,28 +17,49 @@
 
 package org.apache.ignite.ci.issue;
 
+/**
+ * Type of Issue detectable by the Bot.
+ */
 public enum IssueType {
+    /** New failure. */
     newFailure("newFailure", "New test failure"),
-    newContributedTestFailure("newContributedTestFailure",
-        "Recently contributed test failed"),
 
-    newFailureForFlakyTest("newFailureForFlakyTest",
-        "New stable failure of a flaky test"),
+    /** New contributed test failure. */
+    newContributedTestFailure("newContributedTestFailure", "Recently contributed test failed"),
+
+    /** New failure for flaky test. */
+    newFailureForFlakyTest("newFailureForFlakyTest", "New stable failure of a flaky test"),
+
+    /** New critical failure. */
+    newCriticalFailure("newCriticalFailure", "New Critical Failure"),
 
-    newCriticalFailure("newCriticalFailure", "New Critical Failure");
+    /** New trusted suite failure. */
+    newTrustedSuiteFailure("newTrustedSuiteFailure", "New Trusted Suite failure");
 
+    /** Code. */
     private final String code;
+    /** Display name. */
     private final String displayName;
 
+    /**
+     * @param code Code.
+     * @param displayName Display name.
+     */
     private IssueType(String code, String displayName) {
         this.code = code;
         this.displayName = displayName;
     }
 
+    /**
+     *
+     */
     public String code() {
         return code;
     }
 
+    /**
+     *
+     */
     public String displayName() {
         return displayName;
     }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessor.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessor.java
index 1be01b3..86a7641 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessor.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessor.java
@@ -17,16 +17,16 @@
 package org.apache.ignite.ci.tcbot.chain;
 
 import com.google.common.base.Strings;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
 import javax.inject.Inject;
 import org.apache.ignite.ci.IAnalyticsEnabledTeamcity;
 import org.apache.ignite.ci.ITeamcity;
 import org.apache.ignite.ci.analysis.FullChainRunCtx;
-import org.apache.ignite.ci.analysis.MultBuildRunCtx;
+import org.apache.ignite.ci.analysis.SuiteInBranch;
+import org.apache.ignite.ci.analysis.TestInBranch;
 import org.apache.ignite.ci.analysis.mode.LatestRebuildMode;
 import org.apache.ignite.ci.analysis.mode.ProcessLogsMode;
 import org.apache.ignite.ci.di.AutoProfiling;
@@ -36,10 +36,12 @@ import org.apache.ignite.ci.github.pure.IGitHubConnectionProvider;
 import org.apache.ignite.ci.jira.ignited.IJiraIgnited;
 import org.apache.ignite.ci.jira.ignited.IJiraIgnitedProvider;
 import org.apache.ignite.ci.tcbot.visa.BranchTicketMatcher;
-import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
+import org.apache.ignite.ci.teamcity.ignited.IRunHistory;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
 import org.apache.ignite.ci.teamcity.ignited.SyncMode;
+import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync;
 import org.apache.ignite.ci.teamcity.restcached.ITcServerProvider;
 import org.apache.ignite.ci.user.ICredentialsProv;
 import org.apache.ignite.ci.web.model.current.ChainAtServerCurrentStatus;
@@ -73,6 +75,8 @@ public class PrChainsProcessor {
 
     @Inject private BranchTicketMatcher ticketMatcher;
 
+    @Inject private IStringCompactor compactor;
+
     /**
      * @param creds Credentials.
      * @param srvCode Server id.
@@ -157,7 +161,7 @@ public class PrChainsProcessor {
                 runningUpdates.addAndGet(cnt0);
 
             //fail rate reference is always default (master)
-            chainStatus.initFromContext(tcIgnited, ctx, baseBranch);
+            chainStatus.initFromContext(tcIgnited, ctx, baseBranch, compactor);
 
             chainStatus.initJiraAndGitInfo(ticketMatcher, jiraIntegration, gitHubConnIgnited);
         }
@@ -185,78 +189,77 @@ public class PrChainsProcessor {
 
     @Nullable
     public List<SuiteCurrentStatus> getBlockersSuitesStatuses(String buildTypeId, String branchForTc, String srvId,
-        ICredentialsProv prov, SyncMode queued) {
-        List<SuiteCurrentStatus> res = new ArrayList<>();
-
-        TestFailuresSummary summary = getTestFailuresSummary(
-            prov, srvId, buildTypeId, branchForTc,
-            FullQueryParams.LATEST, null, null, false, queued);
+        ICredentialsProv prov, SyncMode syncMode) {
+        //using here non persistent TC allows to skip update statistic
+        IAnalyticsEnabledTeamcity teamcity = tcSrvProvider.server(srvId, prov);
+        ITeamcityIgnited tcIgnited = tcIgnitedProvider.server(srvId, prov);
 
-        boolean noBuilds = summary.servers.stream().anyMatch(s -> s.buildNotFound);
+        List<Integer> hist = tcIgnited.getLastNBuildsFromHistory(buildTypeId, branchForTc, 1);
 
-        if (noBuilds)
-            return null;
+        String baseBranch = ITeamcity.DEFAULT;
 
-        for (ChainAtServerCurrentStatus server : summary.servers) {
-            Map<String, List<SuiteCurrentStatus>> fails = findBlockerFailures(server);
+        final FullChainRunCtx ctx = buildChainProcessor.loadFullChainContext(teamcity,
+            tcIgnited,
+            hist,
+            LatestRebuildMode.LATEST,
+            ProcessLogsMode.SUITE_NOT_COMPLETE,
+            true,
+            baseBranch,
+            syncMode);
 
-            fails.forEach((k, v) -> res.addAll(v));
-        }
+        if (ctx.isFakeStub())
+            return null;
 
-        return res;
+        return findBlockerFailures(ctx, tcIgnited, baseBranch);
     }
 
     /**
-     * @param srv Server.
      * @return Failures for given server.
+     * @param fullChainRunCtx
+     * @param tcIgnited
+     * @param baseBranch
      */
-    private Map<String, List<SuiteCurrentStatus>> findBlockerFailures(ChainAtServerCurrentStatus srv) {
-        Map<String, List<SuiteCurrentStatus>> fails = new LinkedHashMap<>();
+    //todo may avoid creation of UI model for simple comment.
+    private List<SuiteCurrentStatus> findBlockerFailures(FullChainRunCtx fullChainRunCtx, ITeamcityIgnited tcIgnited,
+        String baseBranch) {
+        return fullChainRunCtx
+            .failedChildSuites()
+            .map((ctx) -> {
+                String normalizedBaseBranch = RunHistSync.normalizeBranch(baseBranch);
+                IRunHistory statInBaseBranch = tcIgnited.getSuiteRunHist(new SuiteInBranch(ctx.suiteId(), normalizedBaseBranch));
 
-        for (SuiteCurrentStatus suite : srv.suites) {
-            String suiteRes = suite.result.toLowerCase();
-            String failType = null;
+                String suiteComment = ctx.getPossibleBlockerComment(compactor, statInBaseBranch, tcIgnited.config());
 
-            if (suiteRes.contains("compilation"))
-                failType = "compilation";
+                List<TestFailure> failures =  ctx.getFailedTests().stream().map(occurrence -> {
+                    IRunHistory stat = tcIgnited.getTestRunHist(new TestInBranch(occurrence.getName(), normalizedBaseBranch));
 
-            if (suiteRes.contains("timeout"))
-                failType = "timeout";
+                    String testBlockerComment = occurrence.getPossibleBlockerComment(stat);
 
-            if (suiteRes.contains("exit code"))
-                failType = "exit code";
+                    if (!Strings.isNullOrEmpty(testBlockerComment)) {
+                        final TestFailure failure = new TestFailure();
 
-            if (suiteRes.contains(ProblemOccurrence.JAVA_LEVEL_DEADLOCK.toLowerCase()))
-                failType = "java level deadlock";
+                        failure.initFromOccurrence(occurrence, tcIgnited, ctx.projectId(), ctx.branchName(), baseBranch);
 
-            if (suiteRes.contains(ProblemOccurrence.BUILD_FAILURE_ON_MESSAGE.toLowerCase()))
-                failType = "build failure on message";
+                        return failure;
+                    }
+                    return null;
+                }).filter(Objects::nonNull).collect(Collectors.toList());
 
-            if (suiteRes.contains(ProblemOccurrence.BUILD_FAILURE_ON_METRIC.toLowerCase()))
-                failType = "build failure on metrics";
 
-            if (suiteRes.contains(MultBuildRunCtx.CANCELLED.toLowerCase()))
-                failType = MultBuildRunCtx.CANCELLED.toLowerCase();
+                // test failure based blockers and/or blocker found by suite results
+                if (!failures.isEmpty() || !Strings.isNullOrEmpty(suiteComment)) {
 
-            if (failType == null) {
-                List<TestFailure> failures = new ArrayList<>();
+                    SuiteCurrentStatus suiteUi = new SuiteCurrentStatus();
+                    suiteUi.testFailures = failures;
 
-                for (TestFailure testFailure : suite.testFailures) {
-                    if (testFailure.isNewFailedTest())
-                        failures.add(testFailure);
-                }
-
-                if (!failures.isEmpty()) {
-                    suite.testFailures = failures;
+                    suiteUi.initFromContext(tcIgnited, ctx, baseBranch, compactor, false);
 
-                    failType = "failed tests";
+                    return suiteUi;
                 }
-            }
-
-            if (failType != null)
-                fails.computeIfAbsent(failType, k -> new ArrayList<>()).add(suite);
-        }
 
-        return fails;
+                return null;
+            })
+            .filter(Objects::nonNull)
+            .collect(Collectors.toList());
     }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/TrackedBranchChainsProcessor.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/TrackedBranchChainsProcessor.java
index c118411..9e57a67 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/TrackedBranchChainsProcessor.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/TrackedBranchChainsProcessor.java
@@ -28,6 +28,7 @@ import org.apache.ignite.ci.tcbot.conf.BranchTracked;
 import org.apache.ignite.ci.di.AutoProfiling;
 import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
 import org.apache.ignite.ci.tcbot.conf.TcServerConfig;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
 import org.apache.ignite.ci.teamcity.ignited.SyncMode;
@@ -52,11 +53,13 @@ public class TrackedBranchChainsProcessor {
     @Inject private ITeamcityIgnitedProvider tcIgnitedProv;
 
     /** Tc Bot config. */
-    @Inject private ITcBotConfig tcBotConfig;
+    @Inject private ITcBotConfig tcBotCfg;
 
     /** Chains processor. */
     @Inject private BuildChainProcessor chainProc;
 
+    @Inject private IStringCompactor compactor;
+
     @AutoProfiling
     @NotNull
     public TestFailuresSummary getTrackedBranchTestFailures(
@@ -71,7 +74,7 @@ public class TrackedBranchChainsProcessor {
         final String branchNn = isNullOrEmpty(branch) ? TcServerConfig.DEFAULT_TRACKED_BRANCH_NAME : branch;
         res.setTrackedBranch(branchNn);
 
-        final BranchTracked tracked = tcBotConfig.getTrackedBranches().getBranchMandatory(branchNn);
+        final BranchTracked tracked = tcBotCfg.getTrackedBranches().getBranchMandatory(branchNn);
 
         tracked.chains.stream()
             .filter(chainTracked -> tcIgnitedProv.hasAccess(chainTracked.serverId, creds))
@@ -119,7 +122,7 @@ public class TrackedBranchChainsProcessor {
                 if (cnt > 0)
                     runningUpdates.addAndGet(cnt);
 
-                chainStatus.initFromContext(tcIgnited, ctx, baseBranchTc);
+                chainStatus.initFromContext(tcIgnited, ctx, baseBranchTc, compactor);
 
                 return chainStatus;
             })
@@ -144,7 +147,7 @@ public class TrackedBranchChainsProcessor {
         FullLRTestsSummary summary = new FullLRTestsSummary();
 
         final String branchNn = isNullOrEmpty(branch) ? TcServerConfig.DEFAULT_TRACKED_BRANCH_NAME : branch;
-        final BranchTracked tracked = tcBotConfig.getTrackedBranches().getBranchMandatory(branchNn);
+        final BranchTracked tracked = tcBotCfg.getTrackedBranches().getBranchMandatory(branchNn);
 
         tracked.chains.stream()
             .filter(chainTracked -> tcIgnitedProv.hasAccess(chainTracked.serverId, creds))
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/BranchTracked.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/BranchTracked.java
index b7cecd3..20eff29 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/BranchTracked.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/BranchTracked.java
@@ -21,6 +21,9 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.stream.Stream;
+import javax.validation.constraints.NotNull;
+import org.apache.ignite.ci.issue.IssueType;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * One tracked branch, probably on several servers
@@ -32,6 +35,10 @@ public class BranchTracked {
     /** */
     public List<ChainAtServerTracked> chains = new ArrayList<>();
 
+    /** Disable notifications for the following issue types. See {@link IssueType#code()}  */
+    @Nullable private List<String> disableIssueTypes = new ArrayList<>();
+
+
     /**
      * @return internal identifier of the branch.
      */
@@ -48,4 +55,14 @@ public class BranchTracked {
     public Stream<ChainAtServerTracked> getChainsStream() {
         return getChains().stream();
     }
+
+    /**
+     * @
+     */
+    @NotNull public List<String> disableIssueTypes() {
+        return disableIssueTypes == null || disableIssueTypes.isEmpty()
+            ? Collections.emptyList()
+            : Collections.unmodifiableList(disableIssueTypes);
+    }
+
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/ITcServerConfig.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/ITcServerConfig.java
index a03b66e..e370501 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/ITcServerConfig.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/ITcServerConfig.java
@@ -40,11 +40,22 @@ public interface ITcServerConfig {
     @NotNull public String logsDirectory();
 
     /**
-     * @return
+     * @return internal naming of default tracked branch for this server.
      */
     @NotNull public String defaultTrackedBranch();
 
+    /**
+     * @return set of build parameters codes, which could be used for filtering builds in RunHist/Invocations.
+     */
     @NotNull public Collection<String> filteringParametersKeys();
 
+    /**
+     * @return set of build parameters, which could be used for filtering builds in RunHist/Invocations.
+     */
     @NotNull public Collection<BuildParameterSpec> filteringParameters();
+
+    /**
+     * @return set of suite codes (build type IDs), failures in which should be threated as critical and notified.
+     */
+    @NotNull public Collection<String> trustedSuites();
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/TcServerConfig.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/TcServerConfig.java
index a6660ac..60b9821 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/TcServerConfig.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/TcServerConfig.java
@@ -56,6 +56,9 @@ public class TcServerConfig implements ITcServerConfig {
     /** Build parameters which may be used for filtering. */
     @Nullable private List<BuildParameterSpec> filteringParameters = new ArrayList<>();
 
+    /** Trusted suites. */
+    @Nullable private List<String> trustedSuites = new ArrayList<>();
+
     public TcServerConfig() {
 
     }
@@ -127,6 +130,14 @@ public class TcServerConfig implements ITcServerConfig {
         return Collections.unmodifiableList(filteringParameters);
     }
 
+    /** {@inheritDoc} */
+    @NotNull @Override public Collection<String> trustedSuites() {
+        if (trustedSuites == null || trustedSuites.isEmpty())
+            return Collections.emptySet();
+
+        return Collections.unmodifiableList(trustedSuites);
+    }
+
     /**
      * @param props Properties.
      */
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/IssueDetector.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/IssueDetector.java
index ed830fc..9c3a32b 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/IssueDetector.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/issue/IssueDetector.java
@@ -47,6 +47,7 @@ import org.apache.ignite.ci.mail.SlackSender;
 import org.apache.ignite.ci.tcbot.chain.TrackedBranchChainsProcessor;
 import org.apache.ignite.ci.tcbot.conf.INotificationChannel;
 import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
+import org.apache.ignite.ci.tcbot.conf.ITcServerConfig;
 import org.apache.ignite.ci.tcbot.conf.NotificationsConfig;
 import org.apache.ignite.ci.tcbot.user.IUserStorage;
 import org.apache.ignite.ci.teamcity.ignited.IRunHistory;
@@ -56,12 +57,14 @@ import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
 import org.apache.ignite.ci.teamcity.ignited.SyncMode;
 import org.apache.ignite.ci.teamcity.ignited.change.ChangeCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
+import org.apache.ignite.ci.teamcity.ignited.runhist.InvocationData;
 import org.apache.ignite.ci.user.ICredentialsProv;
 import org.apache.ignite.ci.user.TcHelperUser;
 import org.apache.ignite.ci.web.model.current.ChainAtServerCurrentStatus;
 import org.apache.ignite.ci.web.model.current.SuiteCurrentStatus;
 import org.apache.ignite.ci.web.model.current.TestFailure;
 import org.apache.ignite.ci.web.model.current.TestFailuresSummary;
+import org.jetbrains.annotations.NotNull;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -156,6 +159,19 @@ public class IssueDetector {
 
                 return issueAgeMs <= TimeUnit.HOURS.toMillis(2);
             })
+            .filter(issue -> {
+                long buildStartTs = issue.buildStartTs == null ? 0 : issue.buildStartTs;
+                long buildAgeMs = System.currentTimeMillis() - buildStartTs;
+                long maxBuildAgeToNotify = TimeUnit.DAYS.toMillis(InvocationData.MAX_DAYS) / 2;
+
+                return buildAgeMs <= maxBuildAgeToNotify;
+            })
+            .filter(issue -> {
+                return cfg.getTrackedBranches()
+                    .get(issue.trackedBranchName)
+                    .filter(tb -> !tb.disableIssueTypes().contains(issue.type()))
+                    .isPresent();
+            })
             .forEach(issue -> {
                 List<String> addrs = new ArrayList<>();
 
@@ -242,7 +258,6 @@ public class IssueDetector {
             ITeamcityIgnited tcIgnited = tcProv.server(srvId, creds);
 
             for (SuiteCurrentStatus suiteCurrentStatus : next.suites) {
-
                 String normalizeBranch = normalizeBranch(suiteCurrentStatus.branchName());
 
                 final String trackedBranch = res.getTrackedBranch();
@@ -260,8 +275,17 @@ public class IssueDetector {
         return "New issues found " + newIssues;
     }
 
+    /**
+     * Checks and persists suites failure.
+     *
+     * @param tcIgnited Tc ignited.
+     * @param srvCode Server code.
+     * @param normalizeBranch Normalize branch.
+     * @param suiteFailure Suite failure.
+     * @param trackedBranch Tracked branch.
+     */
     private boolean registerSuiteFailIssues(ITeamcityIgnited tcIgnited,
-        String srvId,
+        String srvCode,
         String normalizeBranch,
         SuiteCurrentStatus suiteFailure,
         String trackedBranch) {
@@ -279,30 +303,52 @@ public class IssueDetector {
 
         Integer firstFailedBuildId = runStat.detectTemplate(EventTemplates.newCriticalFailure);
 
-        if (firstFailedBuildId != null && suiteFailure.hasCriticalProblem != null && suiteFailure.hasCriticalProblem) {
-            IssueKey issueKey = new IssueKey(srvId, firstFailedBuildId, suiteId);
+        if (firstFailedBuildId != null && Boolean.TRUE.equals(suiteFailure.hasCriticalProblem)) {
+            IssueKey issueKey = new IssueKey(srvCode, firstFailedBuildId, suiteId);
 
-            if (issuesStorage.containsIssueKey(issueKey))
-                return false; //duplicate
+            if (!issuesStorage.containsIssueKey(issueKey)) {
+                issuesStorage.saveIssue(createIssueForSuite(tcIgnited, suiteFailure, trackedBranch,
+                    issueKey, IssueType.newCriticalFailure));
 
-            Issue issue = new Issue(issueKey, IssueType.newCriticalFailure);
-            issue.trackedBranchName = trackedBranch;
-            issue.displayName = suiteFailure.name;
-            issue.webUrl = suiteFailure.webToHist;
-            issue.buildStartTs = tcIgnited.getBuildStartTs(issueKey.buildId);
+                issueFound = true;
+            }
+        }
+
+        ITcServerConfig tcCfg = cfg.getTeamcityConfig(srvCode);
 
-            locateChanges(tcIgnited, firstFailedBuildId, issue);
+        if (tcCfg.trustedSuites().contains(suiteId)) {
+            Integer firstTrustedSuiteFailue = runStat.detectTemplate(EventTemplates.newFailure);
 
-            logger.info("Register new issue for suite fail: " + issue);
+            if (firstTrustedSuiteFailue != null) {
+                IssueKey issueKey = new IssueKey(srvCode, firstTrustedSuiteFailue, suiteId);
 
-            issuesStorage.saveIssue(issue);
+                if (!issuesStorage.containsIssueKey(issueKey)) {
+                    issuesStorage.saveIssue(createIssueForSuite(tcIgnited, suiteFailure, trackedBranch,
+                        issueKey, IssueType.newTrustedSuiteFailure));
 
-            issueFound = true;
+                    issueFound = true;
+                }
+            }
         }
 
         return issueFound;
     }
 
+    @NotNull
+    private Issue createIssueForSuite(ITeamcityIgnited tcIgnited, SuiteCurrentStatus suiteFailure, String trackedBranch,
+        IssueKey issueKey, IssueType issType) {
+        Issue issue = new Issue(issueKey, issType);
+        issue.trackedBranchName = trackedBranch;
+        issue.displayName = suiteFailure.name;
+        issue.webUrl = suiteFailure.webToHist;
+        issue.buildStartTs = tcIgnited.getBuildStartTs(issueKey.buildId);
+
+        locateChanges(tcIgnited, issueKey.buildId, issue);
+
+        logger.info("Register new issue for suite fail: " + issue);
+        return issue;
+    }
+
     private void locateChanges(ITeamcityIgnited teamcity, int buildId, Issue issue) {
         final FatBuildCompacted fatBuild = teamcity.getFatBuild(buildId);
         final int[] changes = fatBuild.changes();
@@ -460,9 +506,9 @@ public class IssueDetector {
                 SyncMode.RELOAD_QUEUED
             );
 
-        String issResult = registerIssuesAndNotifyLater(failures, backgroundOpsCreds);
+        String issRes = registerIssuesAndNotifyLater(failures, backgroundOpsCreds);
 
-        return "Tests " + failures.failedTests + " Suites " + failures.failedToFinish + " were checked. " + issResult;
+        return "Tests " + failures.failedTests + " Suites " + failures.failedToFinish + " were checked. " + issRes;
     }
 
     public void stop() {
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/CurrentVisaStatus.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/CurrentVisaStatus.java
index 89da1ce..9ed249e 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/CurrentVisaStatus.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/CurrentVisaStatus.java
@@ -17,5 +17,6 @@
 package org.apache.ignite.ci.tcbot.visa;
 
 public class CurrentVisaStatus {
+    /** Total Blockers count. */
     public Integer blockers;
 }
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 00299bc..279fdce 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
@@ -21,6 +21,22 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.inject.Provider;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+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.ci.ITeamcity;
 import org.apache.ignite.ci.github.GitHubBranch;
 import org.apache.ignite.ci.github.GitHubUser;
@@ -40,12 +56,20 @@ import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
 import org.apache.ignite.ci.tcbot.conf.ITcServerConfig;
 import org.apache.ignite.ci.tcmodel.mute.MuteInfo;
 import org.apache.ignite.ci.tcmodel.result.Build;
-import org.apache.ignite.ci.teamcity.ignited.*;
+import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
+import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
+import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
+import org.apache.ignite.ci.teamcity.ignited.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;
 import org.apache.ignite.ci.user.ICredentialsProv;
-import org.apache.ignite.ci.web.model.*;
+import org.apache.ignite.ci.web.model.ContributionKey;
+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.ci.web.model.current.SuiteCurrentStatus;
 import org.apache.ignite.ci.web.model.current.TestFailure;
 import org.apache.ignite.ci.web.model.hist.FailureSummary;
@@ -56,16 +80,9 @@ import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nonnull;
-import javax.inject.Inject;
-import javax.ws.rs.QueryParam;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.*;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static org.apache.ignite.ci.observer.BuildsInfo.*;
+import static org.apache.ignite.ci.observer.BuildsInfo.CANCELLED_STATUS;
+import static org.apache.ignite.ci.observer.BuildsInfo.FINISHED_STATUS;
+import static org.apache.ignite.ci.observer.BuildsInfo.RUNNING_STATUS;
 import static org.apache.ignite.ci.util.XmlUtil.xmlEscapeText;
 
 /**
@@ -711,14 +728,7 @@ public class TcBotTriggerAndSignOffService {
         if (suitesStatuses == null)
             return status;
 
-        status.blockers = suitesStatuses.stream()
-            .mapToInt(suite -> {
-                if (suite.testFailures.isEmpty())
-                    return 1;
-
-                return suite.testFailures.size();
-            })
-            .sum();
+        status.blockers = suitesStatuses.stream().mapToInt(SuiteCurrentStatus::totalBlockers).sum();
 
         return status;
     }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnitedProvider.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnitedProvider.java
index 24e2a19..f4c5920 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnitedProvider.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnitedProvider.java
@@ -32,7 +32,7 @@ public interface ITeamcityIgnitedProvider {
      */
     public ITeamcityIgnited server(String srvCode, @Nullable ICredentialsProv prov);
 
-    default void checkAccess(@Nullable String srvCode, ICredentialsProv credsProv) {
+    public default void checkAccess(@Nullable String srvCode, ICredentialsProv credsProv) {
         if (!hasAccess(srvCode, credsProv))
             throw ServiceUnauthorizedException.noCreds(srvCode);
     }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProblemCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProblemCompacted.java
index ee0966f..247cf67 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProblemCompacted.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProblemCompacted.java
@@ -186,4 +186,8 @@ public class ProblemCompacted {
             || isBuildFailureOnMetric(compactor)
             || isCompilationError(compactor);
     }
+
+    public boolean isBuildFailureOnMessage(IStringCompactor compactor) {
+        return compactor.getStringId(ProblemOccurrence.BUILD_FAILURE_ON_MESSAGE) == type;
+    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistSync.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistSync.java
index b0662cd..f733b9a 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistSync.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/runhist/RunHistSync.java
@@ -90,7 +90,7 @@ public class RunHistSync {
         if (ITeamcity.REFS_HEADS_MASTER.equals(branch))
             return ITeamcity.DEFAULT;
 
-        if ("master".equals(branch))
+        if (ITeamcity.MASTER.equals(branch))
             return ITeamcity.DEFAULT;
 
         return branch;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/ChainAtServerCurrentStatus.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/ChainAtServerCurrentStatus.java
index 0fb16e6..b617177 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/ChainAtServerCurrentStatus.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/ChainAtServerCurrentStatus.java
@@ -34,6 +34,7 @@ import org.apache.ignite.ci.github.pure.IGitHubConnection;
 import org.apache.ignite.ci.jira.ignited.IJiraIgnited;
 import org.apache.ignite.ci.tcbot.visa.BranchTicketMatcher;
 import org.apache.ignite.ci.tcmodel.conf.BuildType;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
 import org.apache.ignite.ci.util.CollectionUtil;
 import org.apache.ignite.internal.util.typedef.T2;
@@ -113,6 +114,9 @@ public class ChainAtServerCurrentStatus {
 
     @Nullable public String baseBranchForTc;
 
+    /** Total blockers count. */
+    public int totalBlockers;
+
     public ChainAtServerCurrentStatus(String srvId, String branchTc) {
         this.serverId = srvId;
         this.branchName = branchTc;
@@ -130,7 +134,14 @@ public class ChainAtServerCurrentStatus {
         this.webToPr = webToPr;
     }
 
-    /** */
+
+    /**
+     * Set up ticket and PR related information.
+     *
+     * @param ticketMatcher Ticket matcher.
+     * @param jiraIntegration Jira integration.
+     * @param gitHubConnIgnited Git hub connection ignited.
+     */
     public void initJiraAndGitInfo(BranchTicketMatcher ticketMatcher,
         IJiraIgnited jiraIntegration,
         IGitHubConnIgnited gitHubConnIgnited) {
@@ -166,7 +177,7 @@ public class ChainAtServerCurrentStatus {
 
     public void initFromContext(ITeamcityIgnited tcIgnited,
         FullChainRunCtx ctx,
-        @Nullable String baseBranchTc) {
+        @Nullable String baseBranchTc, IStringCompactor compactor) {
         failedTests = 0;
         failedToFinish = 0;
         //todo mode with not failed
@@ -176,15 +187,17 @@ public class ChainAtServerCurrentStatus {
             suite -> {
                 final SuiteCurrentStatus suiteCurStatus = new SuiteCurrentStatus();
 
-                suiteCurStatus.initFromContext(tcIgnited, suite, baseBranchTc);
+                suiteCurStatus.initFromContext(tcIgnited, suite, baseBranchTc, compactor, true);
 
                 failedTests += suiteCurStatus.failedTests;
                 if (suite.hasAnyBuildProblemExceptTestOrSnapshot() || suite.onlyCancelledBuilds())
                     failedToFinish++;
 
-                this.suites.add(suiteCurStatus);
+                suites.add(suiteCurStatus);
             }
         );
+
+        totalBlockers = suites.stream().mapToInt(SuiteCurrentStatus::totalBlockers).sum();
         durationPrintable = ctx.getDurationPrintable();
         testsDurationPrintable = ctx.getTestsDurationPrintable();
         durationNetTimePrintable = ctx.durationNetTimePrintable();
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/SuiteCurrentStatus.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/SuiteCurrentStatus.java
index 454f9dc..136f71d 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/SuiteCurrentStatus.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/SuiteCurrentStatus.java
@@ -29,7 +29,6 @@ import java.util.function.Function;
 import java.util.stream.Collectors;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-import org.apache.ignite.ci.ITeamcity;
 import org.apache.ignite.ci.analysis.IMultTestOccurrence;
 import org.apache.ignite.ci.analysis.MultBuildRunCtx;
 import org.apache.ignite.ci.analysis.SuiteInBranch;
@@ -38,6 +37,7 @@ import org.apache.ignite.ci.analysis.TestLogCheckResult;
 import org.apache.ignite.ci.issue.EventTemplates;
 import org.apache.ignite.ci.issue.ProblemRef;
 import org.apache.ignite.ci.teamcity.ignited.IRunHistory;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
 import org.apache.ignite.ci.web.model.hist.FailureSummary;
 import org.apache.ignite.ci.web.rest.GetBuildLog;
@@ -126,23 +126,26 @@ import static org.apache.ignite.ci.util.UrlUtil.escape;
      */
     @Nullable public ProblemRef problemRef;
 
-    /** Possible blocker: filled for PR and builds checks, mean there was stable execution in master, but */
-    public Boolean possibleBlocker;
-
     public Set<String> tags = new HashSet<>();
 
-    public void initFromContext(ITeamcityIgnited tcIgnited,
+    /**
+     * Possible blocker comment: filled for PR and builds checks, non null value contains problem explanation
+     * displayable.
+     */
+    @Nullable public String blockerComment;
+
+    public SuiteCurrentStatus initFromContext(ITeamcityIgnited tcIgnited,
         @Nonnull final MultBuildRunCtx suite,
-        @Nullable final String baseBranch) {
+        @Nullable final String baseBranch,
+        @Nonnull IStringCompactor compactor,
+        boolean includeTests) {
 
         name = suite.suiteName();
 
         String failRateNormalizedBranch = normalizeBranch(baseBranch);
         String curBranchNormalized = normalizeBranch(suite.branchName());
 
-        String suiteId = suite.suiteId();
-
-        initSuiteStat(tcIgnited, failRateNormalizedBranch, curBranchNormalized, suiteId);
+        IRunHistory baseBranchHist = initSuiteStat(tcIgnited, failRateNormalizedBranch, curBranchNormalized, suite.suiteId());
 
         Set<String> collect = suite.lastChangeUsers().collect(Collectors.toSet());
 
@@ -162,54 +165,55 @@ import static org.apache.ignite.ci.util.UrlUtil.escape;
         webToHistBaseBranch = buildWebLink(tcIgnited, suite, baseBranch);
         webToBuild = buildWebLinkToBuild(tcIgnited, suite);
 
-        List<IMultTestOccurrence> tests = suite.getFailedTests();
-        Function<IMultTestOccurrence, Float> function = foccur -> {
-            TestInBranch testInBranch = new TestInBranch(foccur.getName(), failRateNormalizedBranch);
-
-            IRunHistory apply = tcIgnited.getTestRunHist(testInBranch);
+        if (includeTests) {
+            List<IMultTestOccurrence> tests = suite.getFailedTests();
+            Function<IMultTestOccurrence, Float> function = foccur -> {
+                TestInBranch testInBranch = new TestInBranch(foccur.getName(), failRateNormalizedBranch);
 
-            return apply == null ? 0f : apply.getFailRate();
-        };
+                IRunHistory apply = tcIgnited.getTestRunHist(testInBranch);
 
-        tests.sort(Comparator.comparing(function).reversed());
+                return apply == null ? 0f : apply.getFailRate();
+            };
 
-        tests.forEach(occurrence -> {
-            final TestFailure failure = new TestFailure();
-            failure.initFromOccurrence(occurrence, tcIgnited, suite.projectId(), suite.branchName(), baseBranch);
-            failure.initStat(tcIgnited, failRateNormalizedBranch, curBranchNormalized);
+            tests.sort(Comparator.comparing(function).reversed());
 
-            testFailures.add(failure);
-        });
-
-        suite.getTopLongRunning().forEach(occurrence -> {
-            final TestFailure failure = createOrrucForLongRun(tcIgnited, suite,
-                occurrence, baseBranch);
-
-            topLongRunning.add(failure);
-        });
-
-        suite.getCriticalFailLastStartedTest().forEach(
-            lastTest -> {
+            tests.forEach(occurrence -> {
                 final TestFailure failure = new TestFailure();
-                failure.name = lastTest + " (last started)";
+                failure.initFromOccurrence(occurrence, tcIgnited, suite.projectId(), suite.branchName(), baseBranch);
+                failure.initStat(tcIgnited, failRateNormalizedBranch, curBranchNormalized);
+
                 testFailures.add(failure);
-            }
-        );
+            });
 
-        suite.getLogsCheckResults().forEach(map -> {
-                map.forEach(
-                    (testName, logCheckResult) -> {
-                        if (logCheckResult.hasWarns())
-                            this.findFailureAndAddWarning(testName, logCheckResult);
+            suite.getTopLongRunning().forEach(occurrence -> {
+                final TestFailure failure = createOrrucForLongRun(tcIgnited, suite, occurrence, baseBranch);
 
-                    }
-                );
-            }
-        );
+                topLongRunning.add(failure);
+            });
 
-        suite.getTopLogConsumers().forEach(
-            (entry) -> logConsumers.add(createOccurForLogConsumer(entry))
-        );
+            suite.getCriticalFailLastStartedTest().forEach(
+                lastTest -> {
+                    final TestFailure failure = new TestFailure();
+                    failure.name = lastTest + " (last started)";
+                    testFailures.add(failure);
+                }
+            );
+
+            suite.getLogsCheckResults().forEach(map -> {
+                    map.forEach(
+                        (testName, logCheckResult) -> {
+                            if (logCheckResult.hasWarns())
+                                this.findFailureAndAddWarning(testName, logCheckResult);
+
+                        }
+                    );
+                }
+            );
+
+            suite.getTopLogConsumers().forEach(
+                (entry) -> logConsumers.add(createOccurForLogConsumer(entry))
+            );
+        }
 
         suite.getBuildsWithThreadDump().forEach(buildId -> {
             webUrlThreadDump = "/rest/" + GetBuildLog.GET_BUILD_LOG + "/" + GetBuildLog.THREAD_DUMP
@@ -223,36 +227,37 @@ import static org.apache.ignite.ci.util.UrlUtil.escape;
         serverId = tcIgnited.serverId();
         this.suiteId = suite.suiteId();
         branchName = branchForLink(suite.branchName());
-        // todo implement this logic in suite possibleBlocker = suite.hasPossibleBlocker();
 
         tags = suite.tags();
+
+        blockerComment = suite.getPossibleBlockerComment(compactor, baseBranchHist, tcIgnited.config());
+
+        return this;
     }
 
-    private void initSuiteStat(ITeamcityIgnited tcIgnited,
+    private IRunHistory initSuiteStat(ITeamcityIgnited tcIgnited,
         String failRateNormalizedBranch,
         String curBranchNormalized,
         String suiteId) {
         if (Strings.isNullOrEmpty(suiteId))
-            return;
+            return null;
 
-        SuiteInBranch key = new SuiteInBranch(suiteId, failRateNormalizedBranch);
+        final IRunHistory statInBaseBranch = tcIgnited.getSuiteRunHist(new SuiteInBranch(suiteId, failRateNormalizedBranch));
 
-        final IRunHistory stat = tcIgnited.getSuiteRunHist(key);
+        if (statInBaseBranch != null) {
+            failures = statInBaseBranch.getFailuresCount();
+            runs = statInBaseBranch.getRunsCount();
+            failureRate = statInBaseBranch.getFailPercentPrintable();
 
-        if (stat != null) {
-            failures = stat.getFailuresCount();
-            runs = stat.getRunsCount();
-            failureRate = stat.getFailPercentPrintable();
-
-            criticalFails.failures = stat.getCriticalFailuresCount();
+            criticalFails.failures = statInBaseBranch.getCriticalFailuresCount();
             criticalFails.runs = runs;
-            criticalFails.failureRate = stat.getCriticalFailPercentPrintable();
+            criticalFails.failureRate = statInBaseBranch.getCriticalFailPercentPrintable();
 
-            failsAllHist.failures = stat.getFailuresAllHist();
-            failsAllHist.runs = stat.getRunsAllHist();
-            failsAllHist.failureRate = stat.getFailPercentAllHistPrintable();
+            failsAllHist.failures = statInBaseBranch.getFailuresAllHist();
+            failsAllHist.runs = statInBaseBranch.getRunsAllHist();
+            failsAllHist.failureRate = statInBaseBranch.getFailPercentAllHistPrintable();
 
-            latestRuns = stat.getLatestRunResults();
+            latestRuns = statInBaseBranch.getLatestRunResults();
         }
 
         IRunHistory latestRunsSrc = null;
@@ -265,7 +270,7 @@ import static org.apache.ignite.ci.util.UrlUtil.escape;
             latestRuns = statForStripe != null ? statForStripe.getLatestRunResults() : null;
         }
         else
-            latestRunsSrc = stat;
+            latestRunsSrc = statInBaseBranch;
 
         if (latestRunsSrc != null) {
             if (latestRunsSrc.detectTemplate(EventTemplates.newFailureForFlakyTest) != null)
@@ -274,6 +279,8 @@ import static org.apache.ignite.ci.util.UrlUtil.escape;
             if (latestRunsSrc.detectTemplate(EventTemplates.newCriticalFailure) != null)
                 problemRef = new ProblemRef("New Critical Failure");
         }
+
+        return statInBaseBranch;
     }
 
     @NotNull
@@ -333,7 +340,7 @@ import static org.apache.ignite.ci.util.UrlUtil.escape;
     }
 
     public static String branchForLink(@Nullable String branchName) {
-        return branchName == null || "refs/heads/master".equals(branchName) ? ITeamcity.DEFAULT : branchName;
+        return normalizeBranch(branchName);
     }
 
     /** {@inheritDoc} */
@@ -374,7 +381,7 @@ import static org.apache.ignite.ci.util.UrlUtil.escape;
             Objects.equals(testsDurationPrintable, status.testsDurationPrintable) &&
             Objects.equals(lostInTimeouts, status.lostInTimeouts) &&
             Objects.equals(problemRef, status.problemRef) &&
-            Objects.equals(possibleBlocker, status.possibleBlocker);
+            Objects.equals(blockerComment, status.blockerComment);
     }
 
     /** {@inheritDoc} */
@@ -384,7 +391,7 @@ import static org.apache.ignite.ci.util.UrlUtil.escape;
             runningBuildCount, queuedBuildCount, serverId, suiteId, branchName, failsAllHist, criticalFails, latestRuns,
             userCommits, failedTests, durationPrintable, durationNetTimePrintable, sourceUpdateDurationPrintable,
             artifcactPublishingDurationPrintable, dependeciesResolvingDurationPrintable, testsDurationPrintable,
-            lostInTimeouts, problemRef, possibleBlocker);
+            lostInTimeouts, problemRef, blockerComment);
     }
 
     /** {@inheritDoc} */
@@ -404,4 +411,14 @@ import static org.apache.ignite.ci.util.UrlUtil.escape;
     public String branchName() {
         return branchName;
     }
+
+    public int totalBlockers() {
+        int res = 0;
+        if (!Strings.isNullOrEmpty(blockerComment))
+            res++;
+
+        res += (int)testFailures.stream().filter(TestFailure::isPossibleBlocker).count();
+
+        return res;
+    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/TestFailure.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/TestFailure.java
index ba3a025..90bf9bb 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/TestFailure.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/TestFailure.java
@@ -36,9 +36,9 @@ import org.apache.ignite.ci.web.model.hist.FailureSummary;
 import org.apache.ignite.ci.web.model.hist.TestHistory;
 import org.jetbrains.annotations.NotNull;
 
+import static org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync.normalizeBranch;
 import static org.apache.ignite.ci.util.TimeUtil.millisToDurationPrintable;
 import static org.apache.ignite.ci.util.UrlUtil.escape;
-import static org.apache.ignite.ci.web.model.current.SuiteCurrentStatus.branchForLink;
 
 /**
  * UI model for test failure, probably merged with its history
@@ -88,10 +88,13 @@ import static org.apache.ignite.ci.web.model.current.SuiteCurrentStatus.branchFo
     /** Link to test history for current branch. */
     @Nullable public String webUrlBaseBranch;
 
+    /** Blocker comment: indicates test seems to be introduced failure. */
+    @Nullable public String blockerComment;
+
     /**
-     * @param failure
-     * @param tcIgn
-     * @param projectId
+     * @param failure test ocurrence (probably multiple)
+     * @param tcIgn Teamcity.
+     * @param projectId project ID.
      * @param branchName
      * @param baseBranchName base branch name (e.g. master).
      */
@@ -142,6 +145,9 @@ import static org.apache.ignite.ci.web.model.current.SuiteCurrentStatus.branchFo
                     webUrlBaseBranch = buildWebLink(tcIgn, full.test.id, projectId, baseBranchName);
         });
 
+        final IRunHistory stat = tcIgn.getTestRunHist(new TestInBranch(name, normalizeBranch(baseBranchName)));
+
+        blockerComment = failure.getPossibleBlockerComment(stat);
     }
 
     /**
@@ -176,7 +182,7 @@ import static org.apache.ignite.ci.web.model.current.SuiteCurrentStatus.branchFo
         if (projectId == null)
             return null;
 
-        final String branch = branchForLink(branchName);
+        final String branch = normalizeBranch(branchName);
 
         return tcIgn.host() + "project.html"
             + "?projectId=" + projectId
@@ -194,9 +200,7 @@ import static org.apache.ignite.ci.web.model.current.SuiteCurrentStatus.branchFo
         String failRateNormalizedBranch,
         String curBranchNormalized) {
 
-        TestInBranch testInBranch = new TestInBranch(name, failRateNormalizedBranch);
-
-        final IRunHistory stat = tcIgnited.getTestRunHist(testInBranch);
+        final IRunHistory stat = tcIgnited.getTestRunHist(new TestInBranch(name, failRateNormalizedBranch));
 
         histBaseBranch.init(stat);
 
@@ -228,6 +232,7 @@ import static org.apache.ignite.ci.web.model.current.SuiteCurrentStatus.branchFo
     /**
      * @return {@code True} if this failure is appeared in the current branch.
      */
+    @Deprecated
     public boolean isNewFailedTest() {
         if (!Strings.isNullOrEmpty(webIssueUrl))
             return false;
@@ -265,17 +270,26 @@ import static org.apache.ignite.ci.web.model.current.SuiteCurrentStatus.branchFo
             Objects.equals(problemRef, failure.problemRef) &&
             Objects.equals(histCurBranch, failure.histCurBranch) &&
             Objects.equals(histBaseBranch, failure.histBaseBranch) &&
-            Objects.equals(webUrlBaseBranch, failure.webUrlBaseBranch);
+            Objects.equals(webUrlBaseBranch, failure.webUrlBaseBranch) &&
+            Objects.equals(blockerComment, failure.blockerComment);
     }
 
     /** {@inheritDoc} */
     @Override public int hashCode() {
-        return Objects.hash(name, suiteName, testName, curFailures, webUrl, webIssueUrl, webIssueText, investigated,
-            durationPrintable, warnings, problemRef, histCurBranch, histBaseBranch, webUrlBaseBranch);
+        return Objects.hash(name, suiteName, testName, curFailures, webUrl, webIssueUrl, webIssueText,
+            investigated, durationPrintable, warnings, problemRef, histCurBranch, histBaseBranch,
+            webUrlBaseBranch, blockerComment);
     }
 
     /** {@inheritDoc} */
     @Override public String toString() {
         return "\t" + name + "\n";
     }
+
+    /**
+     *
+     */
+    public boolean isPossibleBlocker() {
+        return !Strings.isNullOrEmpty(blockerComment);
+    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetChainResultsAsHtml.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetChainResultsAsHtml.java
index dc385f5..bb4ae26 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetChainResultsAsHtml.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetChainResultsAsHtml.java
@@ -35,6 +35,7 @@ import org.apache.ignite.ci.ITeamcity;
 import org.apache.ignite.ci.analysis.FullChainRunCtx;
 import org.apache.ignite.ci.analysis.mode.LatestRebuildMode;
 import org.apache.ignite.ci.analysis.mode.ProcessLogsMode;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
 import org.apache.ignite.ci.teamcity.ignited.SyncMode;
@@ -92,7 +93,7 @@ public class GetChainResultsAsHtml {
 
         status.chainName = ctx.suiteName();
 
-        status.initFromContext(tcIgn, ctx, failRateBranch);
+        status.initFromContext(tcIgn, ctx, failRateBranch, injector.getInstance(IStringCompactor.class));
 
         res.append(showChainAtServerData(status));
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/GetBuildTestFailures.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/GetBuildTestFailures.java
index bdc12ad..055d4df 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/GetBuildTestFailures.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/build/GetBuildTestFailures.java
@@ -23,6 +23,7 @@ import java.text.ParseException;
 import com.google.inject.Injector;
 import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
 import org.apache.ignite.ci.tcbot.trends.MasterTrendsService;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.SyncMode;
 import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildCondition;
 import org.apache.ignite.ci.tcbot.chain.BuildChainProcessor;
@@ -144,7 +145,7 @@ public class GetBuildTestFailures {
         if (cnt > 0)
             runningUpdates.addAndGet(cnt);
 
-        chainStatus.initFromContext(tcIgnited, ctx, failRateBranch);
+        chainStatus.initFromContext(tcIgnited, ctx, failRateBranch, injector.getInstance(IStringCompactor.class));
 
         res.addChainOnServer(chainStatus);
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java
index 04b2936..a344b5a 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java
@@ -37,7 +37,6 @@ import org.apache.ignite.ci.user.ICredentialsProv;
 import org.apache.ignite.ci.web.CtxListener;
 import org.apache.ignite.ci.web.model.current.TestFailuresSummary;
 import org.apache.ignite.ci.web.model.current.UpdateInfo;
-import org.apache.ignite.ci.web.rest.exception.ServiceUnauthorizedException;
 import org.apache.ignite.ci.web.rest.parms.FullQueryParams;
 import org.apache.ignite.internal.util.typedef.F;
 import org.jetbrains.annotations.NotNull;
diff --git a/ignite-tc-helper-web/src/main/webapp/all.html b/ignite-tc-helper-web/src/main/webapp/all.html
index 3799112..e6dd691 100644
--- a/ignite-tc-helper-web/src/main/webapp/all.html
+++ b/ignite-tc-helper-web/src/main/webapp/all.html
@@ -11,14 +11,14 @@
     <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="js/common-1.6.js"></script>
-    <script src="js/testfails-2.1.js"></script>
+    <script src="js/testfails-2.2.js"></script>
 </head>
 <body>
 <script>
     var g_shownDataHashCodeHex = "";
 
     $(document).ready(function () {
-        $.getScript("js/testfails-2.1.js", function (data, textStatus, jqxhr) {
+        $.getScript("js/testfails-2.2.js", function (data, textStatus, jqxhr) {
         });
 
         $(document).tooltip();
diff --git a/ignite-tc-helper-web/src/main/webapp/build-comparator.html b/ignite-tc-helper-web/src/main/webapp/build-comparator.html
index 4a45bfe..e8d5da9 100644
--- a/ignite-tc-helper-web/src/main/webapp/build-comparator.html
+++ b/ignite-tc-helper-web/src/main/webapp/build-comparator.html
@@ -9,14 +9,14 @@
     <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
 
     <script src="js/common-1.6.js"></script>
-    <script src="js/testfails-2.1.js"></script>
+    <script src="js/testfails-2.2.js"></script>
 </head>
 <body>
 <script>
     var g_shownDataHashCodeHex = "";
 
     $(document).ready(function() {
-        $.getScript("js/testfails-2.1.js", function(data, textStatus, jqxhr){ });
+        $.getScript("js/testfails-2.2.js", function(data, textStatus, jqxhr){ });
 
         $( document ).tooltip();
         loadData();
diff --git a/ignite-tc-helper-web/src/main/webapp/build.html b/ignite-tc-helper-web/src/main/webapp/build.html
index 50bcadd..c3acdbd 100644
--- a/ignite-tc-helper-web/src/main/webapp/build.html
+++ b/ignite-tc-helper-web/src/main/webapp/build.html
@@ -11,14 +11,14 @@
     <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
 
     <script src="js/common-1.6.js"></script>
-    <script src="js/testfails-2.1.js"></script>
+    <script src="js/testfails-2.2.js"></script>
 </head>
 <body>
 <script>
 var g_shownDataHashCodeHex = "";
 
 $(document).ready(function() {
-    $.getScript("js/testfails-2.1.js", function(data, textStatus, jqxhr){ });
+    $.getScript("js/testfails-2.2.js", function(data, textStatus, jqxhr){ });
     
     $( document ).tooltip();
     loadData();
diff --git a/ignite-tc-helper-web/src/main/webapp/current.html b/ignite-tc-helper-web/src/main/webapp/current.html
index 55caea8..053fb6a 100644
--- a/ignite-tc-helper-web/src/main/webapp/current.html
+++ b/ignite-tc-helper-web/src/main/webapp/current.html
@@ -11,14 +11,14 @@
     <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
 
     <script src="js/common-1.6.js"></script>
-    <script src="js/testfails-2.1.js"></script>
+    <script src="js/testfails-2.2.js"></script>
 </head>
 <body>
 <script>
 var g_shownDataHashCodeHex = "";
 
 $(document).ready(function() {
-    $.getScript("js/testfails-2.1.js", function(data, textStatus, jqxhr){ });
+    $.getScript("js/testfails-2.2.js", function(data, textStatus, jqxhr){ });
     
     $( document ).tooltip();
     loadData();
diff --git a/ignite-tc-helper-web/src/main/webapp/js/testfails-2.1.js b/ignite-tc-helper-web/src/main/webapp/js/testfails-2.2.js
similarity index 92%
rename from ignite-tc-helper-web/src/main/webapp/js/testfails-2.1.js
rename to ignite-tc-helper-web/src/main/webapp/js/testfails-2.2.js
index 04ace45..72222a0 100644
--- a/ignite-tc-helper-web/src/main/webapp/js/testfails-2.1.js
+++ b/ignite-tc-helper-web/src/main/webapp/js/testfails-2.2.js
@@ -242,7 +242,7 @@ function showChainCurrentStatusData(chain, settings) {
         for (var l = 0; l < chain.suites.length; l++) {
             var suite0 = chain.suites[l];
 
-            var suiteOrNull = suiteWithCriticalFailuresOnly(suite0);
+            var suiteOrNull = filterPossibleBlocker(suite0);
 
             if (suiteOrNull != null) {
                 if (blockersList.length !== 0)
@@ -266,7 +266,7 @@ function showChainCurrentStatusData(chain, settings) {
         //     res+="<br>";
 
         if (settings.isJiraAvailable())
-            res+="<br>";
+            res += "<br>";
 
         res += "Base branch";
         res += ": " + chain.baseBranchForTc.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
@@ -305,7 +305,7 @@ function addBlockersData(server, settings) {
     for (var i = 0; i < server.suites.length; i++) {
         var suite = server.suites[i];
 
-        suite = suiteWithCriticalFailuresOnly(suite);
+        suite = filterPossibleBlocker(suite);
 
         if (suite != null)
             blockers += showSuiteData(suite, settings, server.prNum);
@@ -317,9 +317,14 @@ function addBlockersData(server, settings) {
             "<th class='table-title'>Base Branch</th></tr>";
     }
     else {
-        blockers = "<tr bgcolor='#F5F5FF'><th colspan='3' class='table-title'><b>Possible Blockers</b></th>" +
-            "<th class='table-title'>Base Branch</th></tr>" +
-            blockers
+        let blockersHeader = "<tr bgcolor='#F5F5FF'><th colspan='3' class='table-title'><b>Possible Blockers";
+
+        if (isDefinedAndFilled(server.totalBlockers))
+            blockersHeader += " (" + server.totalBlockers + ")";
+
+        blockersHeader += "</b></th>" +  "<th class='table-title'>Base Branch</th></tr>";
+
+        blockers = blockersHeader + blockers;
     }
 
     blockers += "<tr bgcolor='#F5F5FF'><th colspan='3' class='table-title'><b>All Failures</b></th>" +
@@ -334,8 +339,9 @@ function addBlockersData(server, settings) {
  * @param suite - see SuiteCurrentStatus Java class.
  * @returns Suite without flaky tests. Or null - if suite have only flaky tests.
  */
-function suiteWithCriticalFailuresOnly(suite) {
+function filterPossibleBlocker(suite) {
     var suite0 = Object.assign({}, suite);
+
     var j = 0;
 
     suite0.testFailures = suite0.testFailures.slice();
@@ -343,69 +349,19 @@ function suiteWithCriticalFailuresOnly(suite) {
     while (j < suite0.testFailures.length) {
         var testFailure = suite0.testFailures[j];
 
-        if (isNewFailedTest(testFailure) || testFailure.name.includes("(last started)"))
+        if (isDefinedAndFilled(testFailure.blockerComment) && testFailure.blockerComment !== "")
             j++;
         else
             suite0.testFailures.splice(j, 1);
     }
 
-    if (suite0.testFailures.length > 0 || suite0.result !== "")
+    if(isDefinedAndFilled(suite.blockerComment) && suite.blockerComment!=="")
         return suite0;
 
-    return null;
-}
-
-/**
- * Send POST request to change PR status.
- *
- * @returns {string}
- */
-function notifyGit() {
-    var server = g_srv_to_notify_git;
-    var suites = 0;
-    var tests = 0;
-
-    for (let suite of server.suites) {
-        if (suite.result != "") {
-            suites++;
-
-            continue;
-        }
-
-        for (let testFailure of suite.testFailures) {
-            if (isNewFailedTest(testFailure))
-                tests++;
-        }
-    }
-
-    var state;
-    var desc;
-
-    if (suites === 0 && tests === 0) {
-        state = "success";
-        desc = "No blockers found.";
-    }
-    else {
-        state = "failure";
-        desc = suites + " critical suites, " + tests + " failed tests.";
-    }
-
-    var msg = {
-        state: state,
-        target_url: server.webToHist,
-        description: desc,
-        context: "TeamCity"
-    };
-
-    var notifyGitUrl = "rest/pr/notifyGit"  + parmsForRest();
+    if (suite0.testFailures.length > 0)
+        return suite0;
 
-    $.ajax({
-        url: notifyGitUrl,
-        type: 'POST',
-        data: {notifyMsg: JSON.stringify(msg)},
-        success: function(result) {$("#loadStatus").html(result);},
-        error: showErrInLoadStatus
-    });
+    return null;
 }
 
 function triggerBuilds(serverId, parentSuiteId, suiteIdList, branchName, top, observe, ticketId, prNum) {
@@ -632,6 +588,10 @@ function showSuiteData(suite, settings, prNum) {
         }
     }
 
+    if(isDefinedAndFilled(suite.blockerComment) && suite.blockerComment!=="") {
+        res += "<span title='"+ suite.blockerComment +"'> &#x1f6ab;</span> "
+    }
+
     if(isDefinedAndFilled(suite.problemRef)) {
         res += "<span title='"+ suite.problemRef.name +"'>&#128030;</span> "
     }
@@ -691,8 +651,8 @@ function showSuiteData(suite, settings, prNum) {
         mInfo += "Top long running:<br>";
 
         mInfo += "<table>";
-        for (var i = 0; i < suite.topLongRunning.length; i++) {
-            mInfo += showTestFailData(suite.topLongRunning[i], false, settings);
+        for (var j = 0; j < suite.topLongRunning.length; j++) {
+            mInfo += showTestFailData(suite.topLongRunning[j], false, settings);
         }
         mInfo += "</table>";
     }
@@ -700,8 +660,8 @@ function showSuiteData(suite, settings, prNum) {
     if (isDefinedAndFilled(suite.warnOnly) && suite.warnOnly.length > 0) {
         mInfo += "Warn Only:<br>";
         mInfo += "<table>";
-        for (var i = 0; i < suite.warnOnly.length; i++) {
-            mInfo += showTestFailData(suite.warnOnly[i], false, settings);
+        for (var k = 0; k < suite.warnOnly.length; k++) {
+            mInfo += showTestFailData(suite.warnOnly[k], false, settings);
         }
         mInfo += "</table>";
     }
@@ -709,8 +669,8 @@ function showSuiteData(suite, settings, prNum) {
     if (isDefinedAndFilled(suite.logConsumers) && suite.logConsumers.length > 0) {
         mInfo += "Top Log Consumers:<br>";
         mInfo += "<table>";
-        for (var i = 0; i < suite.logConsumers.length; i++) {
-            mInfo += showTestFailData(suite.logConsumers[i], false, settings);
+        for (var l = 0; l < suite.logConsumers.length; l++) {
+            mInfo += showTestFailData(suite.logConsumers[l], false, settings);
         }
         mInfo += "</table>";
     }
@@ -754,32 +714,6 @@ function showSuiteData(suite, settings, prNum) {
     return res;
 }
 
-/**
- * Check that given test is new.
- *
- * @param testFail - see TestFailure Java class.
- * @returns {boolean} True - if test is new. False - otherwise.
- */
-function isNewFailedTest(testFail) {
-    if (isDefinedAndFilled(testFail.webIssueUrl))
-        return false;
-
-    if (!isDefinedAndFilled(testFail.histBaseBranch) || !isDefinedAndFilled(testFail.histBaseBranch.latestRuns))
-        return true;
-
-    var hist = testFail.histBaseBranch;
-
-    if (!isDefinedAndFilled(hist.recent))
-        return true;
-
-    var flakyCommentsInBase =
-        isDefinedAndFilled(testFail.histBaseBranch.flakyComments)
-            ? testFail.histBaseBranch.flakyComments
-            : null;
-
-    return Number.parseFloat(hist.recent.failureRate) < 4.0 && flakyCommentsInBase == null;
-}
-
 function failureRateToColor(failureRate) {
     var redSaturation = 255;
     var greenSaturation = 0;
@@ -870,6 +804,10 @@ function showTestFailData(testFail, isFailureShown, settings) {
         res += baseBranchMarks;
     }
 
+    if (isDefinedAndFilled(testFail.blockerComment) && testFail.blockerComment !== "") {
+        res += "<span title='" + testFail.blockerComment + "'> &#x1f6ab;</span> "
+    }
+
     var bold = false;
     if(isFailureShown && isDefinedAndFilled(testFail.problemRef)) {
         res += "<span title='"+testFail.problemRef.name +"'>&#128030;</span>";
diff --git a/ignite-tc-helper-web/src/main/webapp/monitoring.html b/ignite-tc-helper-web/src/main/webapp/monitoring.html
index 8e708a7..3a45436 100644
--- a/ignite-tc-helper-web/src/main/webapp/monitoring.html
+++ b/ignite-tc-helper-web/src/main/webapp/monitoring.html
@@ -12,7 +12,7 @@
     <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
 
     <script src="js/common-1.6.js"></script>
-    <script src="js/testfails-2.1.js"></script>
+    <script src="js/testfails-2.2.js"></script>
 </head>
 <body>
 <script>
diff --git a/ignite-tc-helper-web/src/main/webapp/pr.html b/ignite-tc-helper-web/src/main/webapp/pr.html
index 8b61c57..01d644b 100644
--- a/ignite-tc-helper-web/src/main/webapp/pr.html
+++ b/ignite-tc-helper-web/src/main/webapp/pr.html
@@ -9,14 +9,14 @@
     <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="js/common-1.6.js"></script>
-    <script src="js/testfails-2.1.js"></script>
+    <script src="js/testfails-2.2.js"></script>
 </head>
 <body>
 <script>
     var g_shownDataHashCodeHex = "";
 
 $(document).ready(function() {
-    $.getScript("js/testfails-2.1.js", function(data, textStatus, jqxhr){ });
+    $.getScript("js/testfails-2.2.js", function(data, textStatus, jqxhr){ });
 
     $( document ).tooltip();
     loadData();
diff --git a/ignite-tc-helper-web/src/main/webapp/prs.html b/ignite-tc-helper-web/src/main/webapp/prs.html
index cd736b4..9d168e3 100644
--- a/ignite-tc-helper-web/src/main/webapp/prs.html
+++ b/ignite-tc-helper-web/src/main/webapp/prs.html
@@ -18,7 +18,7 @@
           integrity="sha384-/rXc/GQVaYpyDdyxK+ecHPVYJSN9bmVFBvjA/9eOB+pb3F2w2N6fc5qB9Ew5yIns" crossorigin="anonymous">
 
     <script src="js/common-1.6.js"></script>
-    <script src="js/testfails-2.1.js"></script>
+    <script src="js/testfails-2.2.js"></script>
     <script src="js/prs-1.1.js"></script>
 
     <style>
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 b2de7bf..e4fd07c 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
@@ -136,12 +136,6 @@ public class PrChainsProcessorTest {
         Optional<TestFailure> testOpt = findBlockerTestFailure(blockers, TEST_WITH_HISTORY_PASSING_IN_MASTER);
         assertTrue(testOpt.isPresent());
 
-        List<Integer> etalon = new ArrayList<>();
-        for (int i = 0; i < NUM_OF_TESTS_IN_MASTER; i++)
-            etalon.add(RunStat.RunStatus.RES_OK.getCode());
-
-        assertEquals(etalon, testOpt.get().histBaseBranch.latestRuns);
-
         assertTrue(containsTestFailure(blockers, TEST_WAS_FIXED_IN_MASTER));
         assertFalse(containsTestFailure(blockers, TEST_WITH_HISTORY_FAILING_IN_MASTER));
         // otherwise this non-blocker will not be filtered out
@@ -178,7 +172,6 @@ public class PrChainsProcessorTest {
         assertTrue(rareNotFlaky.isPresent());
 
         assertNull(rareNotFlaky.get().histBaseBranch.flakyComments);
-        assertTrue(rareNotFlaky.get().histBaseBranch.recent.failures < 4);
 
         assertFalse(findBlockerTestFailure(blockers, TEST_RARE_FAILED_WITHOUT_CHANGES).isPresent());
     }
@@ -454,12 +447,5 @@ public class PrChainsProcessorTest {
 
         Optional<TestFailure> testBecameFailed = findBlockerTestFailure(blockers, TEST_BECAME_FAILED_IN_BRANCH);
         assertTrue(testBecameFailed.isPresent());
-
-        assertNull(testBecameFailed.get().histCurBranch.flakyComments);
-
-        assertNotNull(testBecameFailed.get().problemRef);
-
-        System.err.println(testBecameFailed.get().problemRef.name);
-        assertTrue(testBecameFailed.get().problemRef.name.contains("Failure"));
     }
 }
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java
index 4ab9476..a68f667 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java
@@ -748,6 +748,7 @@ public class IgnitedTcInMemoryIntegrationTest {
             ITcServerConfig tcCfg = mock(ITcServerConfig.class);
             when(tcCfg.logsDirectory()).thenReturn("logs");
             when(tcCfg.host()).thenReturn("http://ci.ignite.apache.org/");
+            when(tcCfg.trustedSuites()).thenReturn(new ArrayList<>());
             when(cfg.getTeamcityConfig(anyString())).thenReturn(tcCfg);
             when(cfg.getTrackedBranches()).thenReturn(new BranchesTracked());
 
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedMock.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedMock.java
index 2354722..8eeea93 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedMock.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedMock.java
@@ -23,6 +23,7 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
 import org.apache.ignite.ci.analysis.TestInBranch;
+import org.apache.ignite.ci.tcbot.conf.ITcServerConfig;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
 import org.apache.ignite.ci.teamcity.ignited.runhist.Invocation;
 import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistCompacted;
@@ -34,6 +35,7 @@ import org.mockito.stubbing.Answer;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 public class TeamcityIgnitedMock {
@@ -118,6 +120,9 @@ public class TeamcityIgnitedMock {
 
         // when(tcIgnited.gitBranchPrefix()).thenReturn("ignite-");
 
+        ITcServerConfig mock = mock(ITcServerConfig.class);
+        when(tcIgnited.config()).thenReturn(mock);
+
         return tcIgnited;
     }
 


Mime
View raw message