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

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


The following commit(s) were added to refs/heads/ignite-10030 by this push:
     new fcd6ae0  IGNITE-10030 changes done in prod: Background upload of 
changes, problems, and statistics
fcd6ae0 is described below

commit fcd6ae0a983a0a2de93aa1147ff240b90d71d342
Author: Dmitriy Pavlov <[email protected]>
AuthorDate: Sat Oct 27 22:11:17 2018 +0300

    IGNITE-10030 changes done in prod: Background upload of changes, problems, 
and statistics
---
 .../main/java/org/apache/ignite/ci/ITeamcity.java  |   2 +
 .../apache/ignite/ci/IgnitePersistentTeamcity.java |  10 ++
 .../apache/ignite/ci/IgniteTeamcityConnection.java |  26 +++--
 .../apache/ignite/ci/analysis/MultBuildRunCtx.java |  39 +++++---
 .../ignite/ci/analysis/SingleBuildRunCtx.java      |  23 +++--
 .../org/apache/ignite/ci/issue/IssueDetector.java  |  16 ++--
 .../ignite/ci/tcbot/chain/BuildChainProcessor.java |  18 +---
 .../tcbot/condition/BuildConditionCompacted.java   |   1 +
 .../ignite/ci/tcmodel/changes/ChangeRef.java       |   4 +
 .../ignite/ci/tcmodel/changes/ChangesList.java     |   5 +
 .../ignite/ci/tcmodel/conf/bt/Parameters.java      |   3 +
 .../ci/teamcity/ignited/ITeamcityIgnited.java      |   4 +
 .../ci/teamcity/ignited/TeamcityIgnitedImpl.java   |  34 +++++++
 .../ci/teamcity/ignited/TeamcityIgnitedModule.java |   4 +
 .../teamcity/ignited/change/ChangeCompacted.java   |  88 +++++++++++++++++
 .../ci/teamcity/ignited/change/ChangeDao.java      | 105 +++++++++++++++++++++
 .../ci/teamcity/ignited/change/ChangeSync.java     |  78 +++++++++++++++
 .../ignited/fatbuild/FatBuildCompacted.java        |  31 ++++--
 .../ci/teamcity/ignited/fatbuild/FatBuildDao.java  |  25 +++++
 .../ignited/fatbuild/ProactiveFatBuildSync.java    |  19 +++-
 .../ignite/ci/teamcity/pure/ITeamcityConn.java     |   7 ++
 .../ignited/IgnitedTcInMemoryIntegrationTest.java  |   8 +-
 22 files changed, 483 insertions(+), 67 deletions(-)

diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITeamcity.java 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITeamcity.java
index dac1546..6fe152c 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITeamcity.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITeamcity.java
@@ -137,8 +137,10 @@ public interface ITeamcity extends ITeamcityConn {
     @Deprecated
     CompletableFuture<TestOccurrenceFull> getTestFull(String href);
 
+    @Deprecated
     Change getChange(String href);
 
+    @Deprecated
     ChangesList getChangesList(String href);
 
     @Deprecated
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java
index 043154c..4f13083 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java
@@ -1161,6 +1161,16 @@ public class IgnitePersistentTeamcity implements 
IAnalyticsEnabledTeamcity, ITea
         return teamcity.getStatistics(buildId);
     }
 
+    @Override
+    public ChangesList getChangesList(int buildId) {
+        return teamcity.getChangesList(buildId);
+    }
+
+    @Override
+    public Change getChange(int changeId) {
+        return teamcity.getChange(changeId);
+    }
+
     /** {@inheritDoc} */
     @Override public void setAuthToken(String tok) {
         teamcity.setAuthToken(tok);
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java
index 9435540..4e99d4e 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java
@@ -325,12 +325,27 @@ public class IgniteTeamcityConnection implements 
ITeamcity {
                 
"&fields=problemOccurrence(id,type,identity,href,details,build(id))", 
ProblemOccurrences.class);
     }
 
-    @Override
     @AutoProfiling
-    public Statistics getStatistics(int buildId) {
+    @Override public Statistics getStatistics(int buildId) {
         return getJaxbUsingHref("app/rest/latest/builds/id:" + buildId + 
"/statistics", Statistics.class);
     }
 
+    @AutoProfiling
+    @Override public ChangesList getChangesList(int buildId) {
+        String href = "app/rest/latest/changes" +
+                "?locator=build:(id:" + + buildId +")" +
+                "&fields=change(id)";
+
+        return getJaxbUsingHref(href, ChangesList.class);
+    }
+
+    @AutoProfiling
+    @Override public Change getChange(int changeId) {
+        String href = "app/rest/latest/changes/id:" + + changeId +"";
+
+        return getJaxbUsingHref(href, Change.class);
+    }
+
     private CompletableFuture<List<File>> unzip(CompletableFuture<File> 
zipFileFut) {
         return zipFileFut.thenApplyAsync(ZipUtil::unZipToSameFolder, executor);
     }
@@ -345,13 +360,6 @@ public class IgniteTeamcityConnection implements ITeamcity 
{
     }
 
     /**
-     * @return Basic auth token.
-     */
-    public String basicAuthToken() {
-        return basicAuthTok;
-    }
-
-    /**
      * @return Normalized Host address, ends with '/'.
      */
     @Override public String host() {
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 c79ab3b..11e0db5 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
@@ -17,24 +17,25 @@
 
 package org.apache.ignite.ci.analysis;
 
-import java.util.*;
-import java.util.concurrent.ConcurrentSkipListMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Future;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import javax.annotation.Nonnull;
-
+import com.google.common.base.Strings;
 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.tcmodel.result.tests.TestOccurrenceFull;
 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;
 import org.apache.ignite.ci.util.CollectionUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import javax.annotation.Nonnull;
+import java.util.*;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
 /**
  * Run configuration execution results loaded from different API URLs.
  * Includes tests and problem occurrences; if logs processing is done also 
contains last started test
@@ -261,9 +262,11 @@ public class MultBuildRunCtx implements ISuiteResults {
     @Nullable
     public Long getBuildDuration() {
         final OptionalDouble average = buildsStream()
-                .mapToLong(SingleBuildRunCtx::getBuildDuration)
+                .map(SingleBuildRunCtx::getBuildDuration)
                 .filter(Objects::nonNull)
+                .mapToLong(l->l)
                 .average();
+
         if(average.isPresent())
             return (long) average.getAsDouble();
 
@@ -307,9 +310,19 @@ public class MultBuildRunCtx implements ISuiteResults {
      */
     public Stream<String> lastChangeUsers() {
         return buildsStream()
-            .flatMap(k -> k.getChanges().stream())
-            .map(change -> change.username)
-            .filter(Objects::nonNull);
+                .flatMap(k -> k.getChanges().stream())
+                .filter(ChangeCompacted::hasUsername)
+                .map(change -> {
+                    final String tcUserFullName = 
change.tcUserFullName(compactor);
+
+                    final String vcsUsername = change.vcsUsername(compactor);
+
+                    if (Strings.isNullOrEmpty(tcUserFullName))
+                        return vcsUsername;
+
+
+                    return vcsUsername + " [" + tcUserFullName + "]";
+                });
     }
 
     Stream<? extends Future<?>> getFutures() {
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 a471a8a..983bebc 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
@@ -28,6 +28,7 @@ import javax.annotation.Nonnull;
 import org.apache.ignite.ci.tcmodel.changes.Change;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrenceFull;
 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.FatBuildCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.ProblemCompacted;
 import org.apache.ignite.ci.util.FutureUtil;
@@ -43,12 +44,12 @@ public class SingleBuildRunCtx implements ISuiteResults {
     /** Compactor. */
     private IStringCompactor compactor;
 
+    /** Changes. */
+    private List<ChangeCompacted> changes = new ArrayList<>();
+
     /** Logger check result future. */
     private CompletableFuture<LogCheckResult> logCheckResFut;
 
-    /** Changes. */
-    private List<Change> changes = new ArrayList<>();
-
     /**
      * @param buildCompacted Build compacted.
      * @param compactor Compactor.
@@ -140,15 +141,8 @@ public class SingleBuildRunCtx implements ISuiteResults {
         return logCheckRes;
     }
 
-    public void addChange(Change change) {
-        if (change.isFakeStub())
-            return;
-
-        this.changes.add(change);
-    }
-
-    public List<Change> getChanges() {
-        return changes;
+    public List<ChangeCompacted> getChanges() {
+        return Collections.unmodifiableList(changes);
     }
 
     public List<TestOccurrenceFull> getTests() {
@@ -197,4 +191,9 @@ public class SingleBuildRunCtx implements ISuiteResults {
     public Long getBuildDuration() {
         return buildCompacted.buildDuration(compactor);
     }
+
+    public void setChanges(Collection<ChangeCompacted> changes) {
+        this.changes.clear();
+        this.changes.addAll(changes);
+    }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/issue/IssueDetector.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/issue/IssueDetector.java
index fce8204..a918fe1 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/issue/IssueDetector.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/issue/IssueDetector.java
@@ -293,15 +293,13 @@ public class IssueDetector {
 
         if (build.changesRef != null) {
             ChangesList changeList = 
teamcity.getChangesList(build.changesRef.href);
-            // System.err.println("changes: " + changeList);
-            if (changeList.changes != null) {
-                for (ChangeRef next : changeList.changes) {
-                    if (!isNullOrEmpty(next.href)) {
-                        // just to cache this change
-                        Change change = teamcity.getChange(next.href);
-
-                        issue.addChange(change.username, change.webUrl);
-                    }
+
+            for (ChangeRef next : changeList.changes()) {
+                if (!isNullOrEmpty(next.href)) {
+                    // just to cache this change
+                    Change change = teamcity.getChange(next.href);
+
+                    issue.addChange(change.username, change.webUrl);
                 }
             }
         }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java
index 8318fa1..602afcb 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java
@@ -47,6 +47,7 @@ import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.tcmodel.result.Build;
 import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
+import org.apache.ignite.ci.teamcity.ignited.change.ChangeCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
 import org.apache.ignite.ci.util.FutureUtil;
 import org.apache.ignite.ci.web.TcUpdatePool;
@@ -183,6 +184,10 @@ public class BuildChainProcessor {
         if (!buildCompacted.isComposite())
             
mCtx.addTests(buildCompacted.getTestOcurrences(compactor).getTests());
 
+        final int[] changeIds = buildCompacted.changes();
+
+        Collection<ChangeCompacted> changes = 
tcIgnited.getAllChanges(changeIds);
+        ctx.setChanges(changes);
 
         //todo migrate rest of the method to fat build from TC ignited
         Build build = teamcity.getBuild(buildRef.getId());
@@ -199,19 +204,6 @@ public class BuildChainProcessor {
             }
         }
 
-        if (build.changesRef != null) {
-            ChangesList changeList = 
teamcity.getChangesList(build.changesRef.href);
-            // System.err.println("changes: " + changeList);
-            if (changeList.changes != null) {
-                for (ChangeRef next : changeList.changes) {
-                    if (!isNullOrEmpty(next.href)) {
-                        // just to cache this change
-                        ctx.addChange(teamcity.getChange(next.href));
-                    }
-                }
-            }
-        }
-
         return ctx;
     }
 
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/condition/BuildConditionCompacted.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/condition/BuildConditionCompacted.java
index 83beee8..430eb8d 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/condition/BuildConditionCompacted.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/condition/BuildConditionCompacted.java
@@ -20,6 +20,7 @@ package org.apache.ignite.ci.tcbot.condition;
 import java.util.Date;
 import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 
+//todo move to ignited package, change cache to 8 partitions
 public class BuildConditionCompacted {
     /** Build id. */
     int buildId = -1;
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/changes/ChangeRef.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/changes/ChangeRef.java
index f01e0f7..4d16034 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/changes/ChangeRef.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/changes/ChangeRef.java
@@ -28,6 +28,10 @@ import org.apache.ignite.ci.tcmodel.result.AbstractRef;
 public class ChangeRef extends AbstractRef {
     @XmlAttribute public String id;
     @XmlAttribute public String version;
+
+    /**
+     * VCS username
+     */
     @XmlAttribute public String username;
     @XmlAttribute public String date;
     @XmlAttribute public String webUrl;
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/changes/ChangesList.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/changes/ChangesList.java
index a7b79d5..8ca0ed2 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/changes/ChangesList.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/changes/ChangesList.java
@@ -17,6 +17,7 @@
 
 package org.apache.ignite.ci.tcmodel.changes;
 
+import java.util.Collections;
 import java.util.List;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -38,4 +39,8 @@ public class ChangesList extends ChangesListRef {
             "changes=" + changes +
             '}';
     }
+
+    public List<ChangeRef> changes() {
+        return changes == null ? Collections.emptyList() : 
Collections.unmodifiableList(changes);
+    }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/bt/Parameters.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/bt/Parameters.java
index b0980a7..0d4e513 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/bt/Parameters.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/bt/Parameters.java
@@ -45,6 +45,9 @@ public class Parameters {
     }
 
     public List<Property> properties() {
+        if(this.properties==null)
+            return Collections.emptyList();
+
         return Collections.unmodifiableList(this.properties);
     }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java
index f7dfba9..9903920 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java
@@ -16,11 +16,13 @@
  */
 package org.apache.ignite.ci.teamcity.ignited;
 
+import java.util.Collection;
 import java.util.List;
 import javax.annotation.Nullable;
 import org.apache.ignite.ci.tcbot.condition.BuildCondition;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.tcmodel.result.Build;
+import org.apache.ignite.ci.teamcity.ignited.change.ChangeCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
 
 /**
@@ -79,4 +81,6 @@ public interface ITeamcityIgnited {
      * @param id Id.
      */
     public FatBuildCompacted getFatBuild(int id);
+
+    public Collection<ChangeCompacted> getAllChanges(int[] changeIds);
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
index 1762693..96a2591 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
@@ -24,8 +24,12 @@ import org.apache.ignite.ci.di.MonitoredTask;
 import org.apache.ignite.ci.di.scheduler.IScheduler;
 import org.apache.ignite.ci.tcbot.condition.BuildCondition;
 import org.apache.ignite.ci.tcbot.condition.BuildConditionDao;
+import org.apache.ignite.ci.tcmodel.changes.Change;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.tcmodel.result.Build;
+import org.apache.ignite.ci.teamcity.ignited.change.ChangeCompacted;
+import org.apache.ignite.ci.teamcity.ignited.change.ChangeDao;
+import org.apache.ignite.ci.teamcity.ignited.change.ChangeSync;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildDao;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.ProactiveFatBuildSync;
@@ -68,6 +72,12 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited 
{
 
     @Inject private ProactiveFatBuildSync buildSync;
 
+    /** Changes DAO. */
+    @Inject private ChangeDao changesDao;
+
+    /** Changes DAO. */
+    @Inject private ChangeSync changeSync;
+
     /** Server ID mask for cache Entries. */
     private int srvIdMaskHigh;
 
@@ -79,6 +89,7 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited {
         buildRefDao.init(); //todo init somehow in auto
         buildConditionDao.init();
         fatBuildDao.init();
+        changesDao.init();
     }
 
 
@@ -146,6 +157,29 @@ public class TeamcityIgnitedImpl implements 
ITeamcityIgnited {
         return savedVer == null ? existingBuild : savedVer;
     }
 
+    @Override
+    public Collection<ChangeCompacted> getAllChanges(int[] changeIds) {
+        final Map<Long, ChangeCompacted> all = 
changesDao.getAll(srvIdMaskHigh, changeIds);
+
+        final Map<Integer, ChangeCompacted> changes = new HashMap<>();
+
+        //todo support change version upgrade
+        all.forEach((k, v) -> {
+            final int changeId = ChangeDao.cacheKeyToChangeId(k);
+
+            changes.put(changeId, v);
+        });
+
+        for (int changeId : changeIds) {
+            if (!changes.containsKey(changeId)) {
+                final ChangeCompacted change = 
changeSync.change(srvIdMaskHigh, changeId, conn);
+
+                changes.put(changeId, change);
+            }
+        }
+
+        return changes.values();
+    }
 
 
     /**
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java
index 9a5d68c..691c6d9 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java
@@ -19,6 +19,8 @@ package org.apache.ignite.ci.teamcity.ignited;
 import com.google.inject.AbstractModule;
 import com.google.inject.internal.SingletonScope;
 import org.apache.ignite.ci.tcbot.condition.BuildConditionDao;
+import org.apache.ignite.ci.teamcity.ignited.change.ChangeDao;
+import org.apache.ignite.ci.teamcity.ignited.change.ChangeSync;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildDao;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.ProactiveFatBuildSync;
 import org.apache.ignite.ci.teamcity.pure.ITeamcityHttpConnection;
@@ -39,6 +41,8 @@ public class TeamcityIgnitedModule extends AbstractModule {
         bind(BuildConditionDao.class).in(new SingletonScope());
         bind(FatBuildDao.class).in(new SingletonScope());
         bind(ProactiveFatBuildSync.class).in(new SingletonScope());
+        bind(ChangeSync.class).in(new SingletonScope());
+        bind(ChangeDao.class).in(new SingletonScope());
 
         bind(IStringCompactor.class).to(IgniteStringCompactor.class).in(new 
SingletonScope());
 
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/ChangeCompacted.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/ChangeCompacted.java
new file mode 100644
index 0000000..619d87a
--- /dev/null
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/ChangeCompacted.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ignite.ci.teamcity.ignited.change;
+
+import org.apache.ignite.ci.analysis.IVersionedEntity;
+import org.apache.ignite.ci.db.Persisted;
+import org.apache.ignite.ci.tcmodel.changes.Change;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
+import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildDao;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Persisted
+public class ChangeCompacted implements IVersionedEntity {
+    /** Logger. */
+    private static final Logger logger = 
LoggerFactory.getLogger(FatBuildDao.class);
+
+    /** Latest version. */
+    private static final int LATEST_VERSION = 1;
+
+    /** Entity fields version. */
+    private short _ver = LATEST_VERSION;
+
+    /**
+     * Change Id, -1 if it is null.
+     */
+    private int id = -1;
+    private int vcsUsername = -1;
+    private int tcUserId = -1;
+    private int tcUserUsername = -1;
+    private int tcUserFullname = -1;
+
+    public ChangeCompacted(IStringCompactor compactor, Change change) {
+        id = compactor.getStringId(change.id);
+        vcsUsername = compactor.getStringId(change.username);
+
+        if (change.user != null) {
+            try {
+                tcUserId = Integer.parseInt(change.user.id);
+            } catch (NumberFormatException e) {
+                logger.error("TC User id parse failed " + change.user.id, e);
+            }
+            tcUserUsername = compactor.getStringId(change.user.username);
+            tcUserFullname = compactor.getStringId(change.user.name);
+        }
+
+    }
+
+    public int id() {
+        return id;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int version() {
+        return _ver;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int latestVersion() {
+        return LATEST_VERSION;
+    }
+
+    public boolean hasUsername() {
+        return vcsUsername>0;
+    }
+
+    public String vcsUsername(IStringCompactor compactor) {
+        return compactor.getStringFromId(vcsUsername);
+    }
+
+    public String tcUserFullName(IStringCompactor compactor) {
+        return compactor.getStringFromId(tcUserFullname);
+    }
+}
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/ChangeDao.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/ChangeDao.java
new file mode 100644
index 0000000..f4a7d9a
--- /dev/null
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/ChangeDao.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ci.teamcity.ignited.change;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.ci.db.TcHelperDb;
+import org.apache.ignite.ci.di.AutoProfiling;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
+import org.apache.ignite.configuration.CacheConfiguration;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+import java.util.*;
+
+public class ChangeDao {
+    /** Cache name */
+    public static final String TEAMCITY_CHANGE_CACHE_NAME = "teamcityChange";
+
+    /** Ignite provider. */
+    @Inject private Provider<Ignite> igniteProvider;
+
+    /** Change Compacted cache. */
+    private IgniteCache<Long, ChangeCompacted> changesCache;
+
+    /** Compactor. */
+    @Inject private IStringCompactor compactor;
+
+    /** */
+    public void init() {
+        CacheConfiguration<Long, ChangeCompacted> cfg = 
TcHelperDb.getCacheV2Config(TEAMCITY_CHANGE_CACHE_NAME);
+
+        changesCache = igniteProvider.get().getOrCreateCache(cfg);
+    }
+
+    /**
+     * @param key Key.
+     * @param srvId Server id.
+     */
+    private boolean isKeyForServer(Long key, int srvId) {
+        return key!=null && key >> 32 == srvId;
+    }
+
+    /**
+     * @param srvId Server id mask high.
+     * @param buildId Build id.
+     */
+    public long changeIdToCacheKey(long srvId, int buildId) {
+        return (long)buildId | srvId << 32;
+    }
+
+    public static int cacheKeyToChangeId(Long cacheKey) {
+        long l = cacheKey << 32;
+        return (int) (l>>32);
+    }
+
+    /**
+     * @param srvId Server id.
+     * @param changeId
+     * @param refCompacted Reference compacted.
+     */
+    @AutoProfiling
+    public boolean save(int srvId, int changeId, ChangeCompacted refCompacted) 
{
+        long cacheKey = changeIdToCacheKey(srvId, changeId);
+        ChangeCompacted changePersisted = changesCache.get(cacheKey);
+
+        if (changePersisted == null || !changePersisted.equals(refCompacted)) {
+            changesCache.put(cacheKey, refCompacted);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    public ChangeCompacted load(int srvId, int changeId) {
+        return changesCache.get(changeIdToCacheKey(srvId, changeId));
+    }
+
+    public Map<Long, ChangeCompacted> getAll(int srvIdMaskHigh, int[] 
changeIds) {
+        final Set<Long> collect = new HashSet<>();
+        for (int changeId : changeIds) {
+            collect.add(changeIdToCacheKey(srvIdMaskHigh, changeId));
+        }
+
+        final Map<Long, ChangeCompacted> all = changesCache.getAll(collect);
+
+        return all;
+    }
+}
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/ChangeSync.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/ChangeSync.java
new file mode 100644
index 0000000..52b7109
--- /dev/null
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/ChangeSync.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ignite.ci.teamcity.ignited.change;
+
+import com.google.common.base.Throwables;
+import org.apache.ignite.ci.tcmodel.changes.Change;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
+import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildDao;
+import org.apache.ignite.ci.teamcity.pure.ITeamcityConn;
+import org.apache.ignite.ci.util.ExceptionUtil;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXParseException;
+
+import javax.inject.Inject;
+import java.io.FileNotFoundException;
+
+public class ChangeSync {
+    /** Logger. */
+    private static final Logger logger = 
LoggerFactory.getLogger(ChangeSync.class);
+
+    /** Changes DAO. */
+    @Inject private ChangeDao changeDao;
+
+    @Inject private IStringCompactor compactor;
+
+    public ChangeCompacted change(int srvId, int changeId, ITeamcityConn conn) 
{
+        final ChangeCompacted load = changeDao.load(srvId, changeId);
+
+        if (load != null && !load.isOutdatedEntityVersion())
+            return load;
+
+        return reloadChange(srvId, changeId, conn);
+    }
+
+    @NotNull
+    public ChangeCompacted reloadChange(int srvId, int changeId, ITeamcityConn 
conn) {
+        Change change;
+        try {
+            change = conn.getChange(changeId);
+        } catch (Exception e) {
+            if (Throwables.getRootCause(e) instanceof FileNotFoundException) {
+                logger.info("Loading changeId [" + changeId + "] for server [" 
+ conn.serverId() + "] failed:" + e.getMessage(), e);
+
+                change = new Change();
+            } else if (Throwables.getRootCause(e) instanceof 
SAXParseException) {
+                System.err.println("Change data seems to be invalid: [" + 
changeId + "]");
+
+                //can re-queue this change without details
+                change = new Change();
+                change.id = Integer.toString(changeId);
+            } else {
+                throw ExceptionUtil.propagateException(e);
+            }
+        }
+
+        final ChangeCompacted changeCompacted = new ChangeCompacted(compactor, 
change);
+
+        changeDao.save(srvId, changeId, changeCompacted);
+
+        return changeCompacted;
+    }
+}
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
index bbbeb9f..3e5774a 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
@@ -17,12 +17,6 @@
 package org.apache.ignite.ci.teamcity.ignited.fatbuild;
 
 import com.google.common.base.Objects;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 import org.apache.ignite.ci.analysis.IVersionedEntity;
 import org.apache.ignite.ci.db.Persisted;
 import org.apache.ignite.ci.tcmodel.conf.BuildType;
@@ -38,6 +32,13 @@ import 
org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
 /**
  *
  */
@@ -83,6 +84,8 @@ public class FatBuildCompacted extends BuildRefCompacted 
implements IVersionedEn
 
     @Nullable private StatisticsCompacted statistics;
 
+    @Nullable private int changesIds[];
+
     /** {@inheritDoc} */
     @Override public int version() {
         return _ver;
@@ -266,13 +269,14 @@ public class FatBuildCompacted extends BuildRefCompacted 
implements IVersionedEn
             Objects.equal(snapshotDeps, that.snapshotDeps) &&
             Objects.equal(flags, that.flags) &&
                 Objects.equal(problems, that.problems) &&
-                Objects.equal(statistics, that.statistics);
+                Objects.equal(statistics, that.statistics)
+                && Objects.equal(changesIds, that.changesIds);
     }
 
     /** {@inheritDoc} */
     @Override public int hashCode() {
         return Objects.hashCode(super.hashCode(), _ver, startDate, finishDate, 
queuedDate, projectId, name, tests,
-                snapshotDeps, flags, problems, statistics);
+                snapshotDeps, flags, problems, statistics, changesIds);
     }
 
     /**
@@ -344,4 +348,15 @@ public class FatBuildCompacted extends BuildRefCompacted 
implements IVersionedEn
     public void statistics(IStringCompactor compactor, Statistics statistics) {
         this.statistics = new StatisticsCompacted(compactor, statistics);
     }
+
+    public void changes(int[] changes) {
+        this.changesIds = changes;
+    }
+
+    public int[] changes() {
+        if(changesIds==null)
+            return new int[0];
+
+        return changesIds;
+    }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildDao.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildDao.java
index da8c789..3a82f35 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildDao.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildDao.java
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.function.IntPredicate;
 import java.util.stream.Collectors;
 import javax.inject.Inject;
 import javax.inject.Provider;
@@ -30,17 +31,23 @@ import javax.validation.constraints.NotNull;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.ci.db.TcHelperDb;
+import org.apache.ignite.ci.tcmodel.changes.ChangesList;
 import org.apache.ignite.ci.tcmodel.result.Build;
 import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
 import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrencesFull;
 import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  *
  */
 public class FatBuildDao {
+    /** Logger. */
+    private static final Logger logger = 
LoggerFactory.getLogger(FatBuildDao.class);
+
     /** Cache name */
     public static final String TEAMCITY_FAT_BUILD_CACHE_NAME = 
"teamcityFatBuild";
 
@@ -67,6 +74,7 @@ public class FatBuildDao {
      * @param tests TestOccurrences one or several pages.
      * @param problems
      * @param statistics
+     * @param changesList
      * @param existingBuild existing version of build in the DB.
      * @return Fat Build saved (if modifications detected), otherwise null.
      */
@@ -76,6 +84,7 @@ public class FatBuildDao {
                                        @NotNull List<TestOccurrencesFull> 
tests,
                                        @Nullable List<ProblemOccurrence> 
problems,
                                        @Nullable Statistics statistics,
+                                       @Nullable ChangesList changesList,
                                        @Nullable FatBuildCompacted 
existingBuild) {
         Preconditions.checkNotNull(buildsCache, "init() was not called");
         Preconditions.checkNotNull(build, "build can't be null");
@@ -91,6 +100,9 @@ public class FatBuildDao {
         if (statistics != null)
             newBuild.statistics(compactor, statistics);
 
+        if (changesList != null)
+            newBuild.changes(extractChangeIds(changesList));
+
         if (existingBuild == null || !existingBuild.equals(newBuild)) {
             buildsCache.put(buildIdToCacheKey(srvIdMaskHigh, buildId), 
newBuild);
 
@@ -100,6 +112,19 @@ public class FatBuildDao {
         return null;
     }
 
+    public static int[] extractChangeIds(@NotNull ChangesList changesList) {
+        return changesList.changes().stream().mapToInt(
+                        ch -> {
+                            try {
+                                return Integer.parseInt(ch.id);
+                            } catch (Exception e) {
+                                logger.error("Unable to parse change id ", e);
+                                return -1;
+                            }
+                        }
+                ).filter(id -> id > 0).toArray();
+    }
+
     /**
      * @param srvIdMaskHigh Server id mask high.
      * @param buildId Build id.
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
index a99463d..f6985e2 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
@@ -21,6 +21,7 @@ import com.google.common.base.Throwables;
 import org.apache.ignite.ci.di.AutoProfiling;
 import org.apache.ignite.ci.di.MonitoredTask;
 import org.apache.ignite.ci.di.scheduler.IScheduler;
+import org.apache.ignite.ci.tcmodel.changes.ChangesList;
 import org.apache.ignite.ci.tcmodel.result.Build;
 import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
 import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
@@ -28,6 +29,7 @@ import 
org.apache.ignite.ci.tcmodel.result.tests.TestOccurrencesFull;
 import org.apache.ignite.ci.teamcity.ignited.BuildRefDao;
 import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
+import org.apache.ignite.ci.teamcity.ignited.change.ChangeSync;
 import org.apache.ignite.ci.teamcity.pure.ITeamcityConn;
 import org.apache.ignite.ci.util.ExceptionUtil;
 import org.jetbrains.annotations.NotNull;
@@ -61,6 +63,8 @@ public class ProactiveFatBuildSync {
 
     @Inject private IStringCompactor compactor;
 
+    @Inject private ChangeSync changeSync;
+
     @GuardedBy("this")
     private Map<String, SyncTask> buildToLoad = new HashMap<>();
 
@@ -217,6 +221,7 @@ public class ProactiveFatBuildSync {
         List<TestOccurrencesFull> tests = new ArrayList<>();
         List<ProblemOccurrence> problems = null;
         Statistics statistics = null;
+        ChangesList changesList = null;
         try {
             build = conn.getBuild(buildId);
 
@@ -235,8 +240,18 @@ public class ProactiveFatBuildSync {
             if (build.problemOccurrences != null)
                 problems = conn.getProblems(buildId).getProblemsNonNull();
 
-            if(build.statisticsRef!=null)
+            if (build.statisticsRef != null)
                 statistics = conn.getStatistics(buildId);
+
+            if (build.changesRef != null) {
+                changesList = conn.getChangesList(buildId);
+
+                for (int changeId : FatBuildDao.extractChangeIds(changesList)) 
{
+                    // consult change sync for provided changes data
+
+                    changeSync.reloadChange(srvIdMask, changeId, conn);
+                }
+            }
         }
         catch (Exception e) {
             if (Throwables.getRootCause(e) instanceof FileNotFoundException) {
@@ -266,6 +281,6 @@ public class ProactiveFatBuildSync {
 
         //if we are here because of some sort of outdated version of build,
         // new save will be performed with new entity version for compacted 
build
-        return fatBuildDao.saveBuild(srvIdMask, buildId, build, tests, 
problems, statistics, existingBuild);
+        return fatBuildDao.saveBuild(srvIdMask, buildId, build, tests, 
problems, statistics, changesList, existingBuild);
     }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java
index 27f6fe9..52ae38b 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java
@@ -21,6 +21,9 @@ import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+
+import org.apache.ignite.ci.tcmodel.changes.Change;
+import org.apache.ignite.ci.tcmodel.changes.ChangesList;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.tcmodel.result.Build;
 import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrences;
@@ -65,4 +68,8 @@ public interface ITeamcityConn {
     ProblemOccurrences getProblems(int buildId);
 
     Statistics getStatistics(int buildId);
+
+    ChangesList getChangesList(int buildId);
+
+    Change getChange(int changeId);
 }
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 e2649a5..489cebc 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
@@ -37,6 +37,7 @@ import org.apache.ignite.ci.db.TcHelperDb;
 import org.apache.ignite.ci.di.scheduler.DirectExecNoWaitSheduler;
 import org.apache.ignite.ci.di.scheduler.IScheduler;
 import org.apache.ignite.ci.di.scheduler.NoOpSheduler;
+import org.apache.ignite.ci.tcmodel.changes.ChangesList;
 import org.apache.ignite.ci.tcmodel.conf.BuildType;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.tcmodel.result.Build;
@@ -257,6 +258,7 @@ public class IgnitedTcInMemoryIntegrationTest {
         TestOccurrencesFull testsRef = jaxbTestXml("/testList.xml", 
TestOccurrencesFull.class);
         ProblemOccurrences problemsList = jaxbTestXml("/problemList.xml", 
ProblemOccurrences.class);
         Statistics statistics = jaxbTestXml("/statistics.xml", 
Statistics.class);
+        ChangesList changesList = jaxbTestXml("/changeList.xml", 
ChangesList.class);
 
         Injector injector = Guice.createInjector(new AbstractModule() {
             @Override protected void configure() {
@@ -271,7 +273,7 @@ public class IgnitedTcInMemoryIntegrationTest {
         int srvIdMaskHigh = ITeamcityIgnited.serverIdToInt(APACHE);
         List<TestOccurrencesFull> occurrences = 
Collections.singletonList(testsRef);
         FatBuildCompacted buildCompacted = stor.saveBuild(srvIdMaskHigh, 
refBuild.getId(), refBuild, occurrences,
-                problemsList.getProblemsNonNull(), statistics, null);
+                problemsList.getProblemsNonNull(), statistics, changesList, 
null);
         assertNotNull(buildCompacted);
 
         FatBuildCompacted fatBuild = stor.getFatBuild(srvIdMaskHigh, 2153237);
@@ -317,6 +319,10 @@ public class IgnitedTcInMemoryIntegrationTest {
         Long duration = buildCompacted.buildDuration(compactor);
         assertNotNull(duration);
         assertTrue(duration>10000L);
+
+        int[] ch = buildCompacted.changes();
+
+        assertEquals(6, ch.length);
     }
 
     public void saveTmpFile(Object obj, String name) throws IOException, 
JAXBException {

Reply via email to