You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by dp...@apache.org on 2019/03/12 15:46:02 UTC

[ignite-teamcity-bot] branch master updated: IGNITE-11461: Revisions were added to JAXB model & Compacted DB model (#115)

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 a45ae60  IGNITE-11461: Revisions were added to JAXB model & Compacted DB model  (#115)
a45ae60 is described below

commit a45ae604c31e804dabff15a5b5988f2f2164fcf7
Author: Dmitriy Pavlov <dp...@apache.org>
AuthorDate: Tue Mar 12 18:45:38 2019 +0300

    IGNITE-11461: Revisions were added to JAXB model & Compacted DB model  (#115)
---
 .../tcbot/visa/TcBotTriggerAndSignOffService.java  |  23 +---
 .../apache/ignite/ci/tcmodel/ParameterType.java    |   1 -
 .../org/apache/ignite/ci/tcmodel/result/Build.java |  23 +++-
 .../org/apache/ignite/ci/tcmodel/vcs/Revision.java |  83 ++++++++++++
 .../apache/ignite/ci/tcmodel/vcs/Revisions.java    |  31 +++++
 .../ignite/ci/tcmodel/vcs/VcsRootInstance.java     |  54 ++++++++
 .../ci/teamcity/ignited/ITeamcityIgnited.java      |  36 ++++++
 .../teamcity/ignited/change/ChangeCompacted.java   |  11 +-
 .../teamcity/ignited/change/RevisionCompacted.java | 139 +++++++++++++++++++++
 .../ignited/fatbuild/FatBuildCompacted.java        |  83 +++++++++---
 .../ignited/IgnitedTcInMemoryIntegrationTest.java  |  19 +++
 11 files changed, 460 insertions(+), 43 deletions(-)

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 e539678..6ca04b3 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
@@ -60,7 +60,6 @@ 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.change.ChangeCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
 import org.apache.ignite.ci.user.ICredentialsProv;
 import org.apache.ignite.ci.web.model.ContributionKey;
@@ -608,25 +607,11 @@ public class TcBotTriggerAndSignOffService {
 
             FatBuildCompacted fatBuild = teamcity.getFatBuild(buildRefCompacted.id(), SyncMode.NONE);
 
-            int changeMax = -1;
-            int[] changes = fatBuild.changes();
-            for (int i = 0; i < changes.length; i++) {
-                int change = changes[i];
-                if (change > changeMax)
-                    changeMax = change;
-            }
+            String commit = teamcity.getLatestCommitVersion(fatBuild);
 
-            if (changeMax > 0) {
-                final Collection<ChangeCompacted> allChanges = teamcity.getAllChanges(new int[] {changeMax});
-                allChanges.stream().findAny().ifPresent(
-                    compacted -> {
-                        String commit = compacted.commitFullVersion();
-                        if (!Strings.isNullOrEmpty(commit)) {
-                            status.finishedSuiteCommit
-                                = commit.substring(0, PullRequest.INCLUDE_SHORT_VER).toLowerCase();
-                        }
-                    }
-                );
+            if (!Strings.isNullOrEmpty(commit) && commit.length() > PullRequest.INCLUDE_SHORT_VER) {
+                status.finishedSuiteCommit
+                    = commit.substring(0, PullRequest.INCLUDE_SHORT_VER).toLowerCase();
             }
         }
         else {
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/ParameterType.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/ParameterType.java
index 3e49969..bdfd766 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/ParameterType.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/ParameterType.java
@@ -44,7 +44,6 @@ import javax.xml.bind.annotation.XmlType;
 @XmlAccessorType(XmlAccessType.FIELD)
 @XmlType(name = "parameterType")
 public class ParameterType {
-
     @XmlAttribute(name = "rawValue")
     protected String rawValue;
 
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/Build.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/Build.java
index 59f9eae..9af0c1b 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/Build.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/Build.java
@@ -29,13 +29,13 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlTransient;
-import org.apache.ignite.ci.analysis.IVersionedEntity;
-import org.apache.ignite.ci.tcmodel.changes.ChangesList;
 import org.apache.ignite.ci.tcmodel.changes.ChangesListRef;
 import org.apache.ignite.ci.tcmodel.conf.BuildType;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
-
+import org.apache.ignite.ci.tcmodel.vcs.Revision;
+import org.apache.ignite.ci.tcmodel.vcs.Revisions;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import static org.apache.ignite.ci.util.ExceptionUtil.propagateException;
 
@@ -71,6 +71,8 @@ public class Build extends BuildRef {
     /** Information about build triggering. */
     @XmlElement(name = "triggered") private Triggered triggered;
 
+    @XmlElement(name = "revisions") private Revisions revisions;
+
     @NotNull public static Build createFakeStub() {
         return new Build();
     }
@@ -170,4 +172,19 @@ public class Build extends BuildRef {
     public void snapshotDependencies(List<BuildRef> dependencies) {
         snapshotDependencies = dependencies;
     }
+
+    /**
+     *
+     */
+    @Nullable public Revisions getRevisions() {
+        return revisions;
+    }
+
+    /**
+     * @param revisions Revisions.
+     */
+    public void setRevisions(List<Revision> revisions) {
+        this.revisions = new Revisions();
+        this.revisions.revisions(revisions);
+    }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/vcs/Revision.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/vcs/Revision.java
new file mode 100644
index 0000000..ae2ffd7
--- /dev/null
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/vcs/Revision.java
@@ -0,0 +1,83 @@
+/*
+ * 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.tcmodel.vcs;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Revision {
+    @XmlAttribute(name = "version")
+    private String version;
+
+    @XmlAttribute(name = "vcsBranchName")
+    private String vcsBranchName;
+
+    @XmlElement(name = "vcs-root-instance")
+    private VcsRootInstance vcsRootInstance;
+
+    public Revision() {
+    }
+
+    /**
+     *
+     */
+    public String version() {
+        return version;
+    }
+
+    /**
+     *
+     */
+    public String vcsBranchName() {
+        return vcsBranchName;
+    }
+
+    /**
+     * @param ver Version.
+     */
+    public Revision version(String ver) {
+        this.version = ver;
+
+        return this;
+    }
+
+    /**
+     *
+     */
+    public VcsRootInstance vcsRootInstance() {
+        return vcsRootInstance;
+    }
+
+    public Revision vcsBranchName(String vcsBranchName) {
+        this.vcsBranchName = vcsBranchName;
+
+        return this;
+    }
+
+    public Revision vcsRootInstance(VcsRootInstance vcsRootInstance) {
+        this.vcsRootInstance = vcsRootInstance;
+
+        return this;
+    }
+}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/vcs/Revisions.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/vcs/Revisions.java
new file mode 100644
index 0000000..1b20a91
--- /dev/null
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/vcs/Revisions.java
@@ -0,0 +1,31 @@
+package org.apache.ignite.ci.tcmodel.vcs;
+
+import java.util.Collections;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Revisions {
+    @XmlAttribute(name = "count")
+    private Integer count;
+
+    @XmlElement(name = "revision")
+    private List<Revision> revisions;
+
+    @Nonnull
+    public List<Revision> revisions() {
+        if (revisions == null)
+            return Collections.emptyList();
+
+        return Collections.unmodifiableList(revisions);
+    }
+
+    public void revisions(List<Revision> revisions) {
+        this.revisions = revisions;
+        this.count = revisions.size();
+    }
+}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/vcs/VcsRootInstance.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/vcs/VcsRootInstance.java
new file mode 100644
index 0000000..c3aa4b3
--- /dev/null
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/vcs/VcsRootInstance.java
@@ -0,0 +1,54 @@
+/*
+ * 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.tcmodel.vcs;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+
+/**
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+public class VcsRootInstance {
+    @XmlAttribute(name = "id")
+    private Integer id;
+
+    @XmlAttribute(name = "vcs-root-id")
+    private String vcsRootId;
+
+    public Integer id() {
+        return id;
+    }
+
+    public String vcsRootId() {
+        return vcsRootId;
+    }
+
+    public VcsRootInstance id(Integer id) {
+        this.id = id;
+
+        return this;
+    }
+
+    public VcsRootInstance vcsRootId(String vcsRootId) {
+        this.vcsRootId = vcsRootId;
+
+        return this;
+    }
+}
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 e1eca89..77301e0 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,9 +16,11 @@
  */
 package org.apache.ignite.ci.teamcity.ignited;
 
+import com.google.common.base.Strings;
 import java.util.Collection;
 import java.util.Date;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 import javax.annotation.Nullable;
 import org.apache.ignite.ci.analysis.SuiteInBranch;
@@ -30,6 +32,7 @@ import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildCondition;
 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.change.ChangeCompacted;
+import org.apache.ignite.ci.teamcity.ignited.change.RevisionCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
 import org.apache.ignite.ci.user.ICredentialsProv;
 import org.jetbrains.annotations.NotNull;
@@ -197,4 +200,37 @@ public interface ITeamcityIgnited {
      * @return List of teamcity agents.
      */
     public List<Agent> agents(boolean connected, boolean authorized);
+
+    /**
+     * @param build Build.
+     */
+    @Nullable
+    public default String getLatestCommitVersion(FatBuildCompacted build) {
+        List<RevisionCompacted> revisions = build.revisions();
+        if (revisions != null) {
+            Optional<String> any = revisions.stream()
+                .map(RevisionCompacted::commitFullVersion)
+                .filter(s -> !Strings.isNullOrEmpty(s))
+                .findAny();
+
+            if (any.isPresent())
+                return any.get(); // Not so good for several VCS roots, probably should use collection here and concatenate.
+        }
+
+        //fallback version of commit hash extraction
+        int changeMax = -1;
+        int[] changes = build.changes();
+        for (int i = 0; i < changes.length; i++) {
+            int change = changes[i];
+            if (change > changeMax)
+                changeMax = change;
+        }
+
+        if (changeMax > 0) {
+            final Collection<ChangeCompacted> allChanges = getAllChanges(new int[] {changeMax});
+            return allChanges.stream().findAny().map(ChangeCompacted::commitFullVersion).orElse(null);
+        }
+
+        return null;
+    }
 }
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
index d582102..73a35a4 100644
--- 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
@@ -16,8 +16,9 @@
  */
 package org.apache.ignite.ci.teamcity.ignited.change;
 
-import com.google.common.base.Objects;
 import com.google.common.base.Strings;
+import java.util.Arrays;
+import java.util.Objects;
 import javax.annotation.Nullable;
 import javax.xml.bind.DatatypeConverter;
 import org.apache.ignite.ci.analysis.IVersionedEntity;
@@ -135,18 +136,20 @@ public class ChangeCompacted implements IVersionedEntity {
             tcUserUsername == compacted.tcUserUsername &&
             tcUserFullname == compacted.tcUserFullname &&
             date == compacted.date &&
-            Objects.equal(version, compacted.version);
+            Arrays.equals(version, compacted.version);
     }
 
     /** {@inheritDoc} */
     @Override public int hashCode() {
-        return Objects.hashCode(_ver, id, vcsUsername, tcUserId, tcUserUsername, tcUserFullname, version, date);
+        int result = Objects.hash(_ver, id, vcsUsername, tcUserId, tcUserUsername, tcUserFullname, date);
+        result = 31 * result + Arrays.hashCode(version);
+        return result;
     }
 
     /**
      *
      */
     public String commitFullVersion() {
-        return DatatypeConverter.printHexBinary(version);
+        return DatatypeConverter.printHexBinary(version).toLowerCase();
     }
 }
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/RevisionCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/RevisionCompacted.java
new file mode 100644
index 0000000..c7de5fc
--- /dev/null
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/change/RevisionCompacted.java
@@ -0,0 +1,139 @@
+/*
+ * 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.Strings;
+import java.util.Arrays;
+import java.util.Objects;
+import javax.annotation.Nullable;
+import javax.xml.bind.DatatypeConverter;
+import org.apache.ignite.ci.analysis.IVersionedEntity;
+import org.apache.ignite.ci.db.Persisted;
+import org.apache.ignite.ci.tcmodel.vcs.Revision;
+import org.apache.ignite.ci.tcmodel.vcs.VcsRootInstance;
+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;
+
+/**
+ * Compacted version of {@link Revision} and its aggregated classes fields.
+ */
+@Persisted
+public class RevisionCompacted implements IVersionedEntity {
+    /** Logger. */
+    private static final Logger logger = LoggerFactory.getLogger(FatBuildDao.class);
+
+    /** Latest version. */
+    private static final int LATEST_VERSION = 1;
+
+    /** Entity fields version. */
+    @SuppressWarnings("FieldCanBeLocal")
+    private short _ver = LATEST_VERSION;
+
+    /** Version: For Git revision, 20 bytes. */
+    @Nullable private byte[] version;
+
+    /** VCS branch (compactor style compacted) Name. */
+    private int vcsBranchName = -1;
+
+    /** Vcs root (compactor style compacted) ID. */
+    private int vcsRootId = -1;
+
+    /** Vcs root instance id. */
+    private int vcsRootInstanceId = -1;
+
+    /**
+     * @param compactor Compactor.
+     * @param revision Revision.
+     */
+    public RevisionCompacted(IStringCompactor compactor, Revision revision) {
+        VcsRootInstance vcsRootInstance = revision.vcsRootInstance();
+        if (vcsRootInstance != null) {
+            vcsRootId = compactor.getStringId(vcsRootInstance.vcsRootId());
+            vcsRootInstanceId = vcsRootInstance.id() != null ? vcsRootInstance.id() : -1;
+        }
+        vcsBranchName = compactor.getStringId(revision.vcsBranchName());
+
+        String ver = revision.version();
+
+        if (!Strings.isNullOrEmpty(ver)) {
+            try {
+                this.version = DatatypeConverter.parseHexBinary(ver);
+            }
+            catch (Exception e) {
+                logger.error("TC Change version parse failed " + ver + ":" + e.getMessage(), e);
+            }
+        }
+
+        vcsBranchName = compactor.getStringId(revision.vcsBranchName());
+
+    }
+
+    /** {@inheritDoc} */
+    @Override public int version() {
+        return _ver;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int latestVersion() {
+        return LATEST_VERSION;
+    }
+
+    public String vcsBranchName(IStringCompactor compactor) {
+        return compactor.getStringFromId(vcsBranchName);
+    }
+
+    public String vcsRootId(IStringCompactor compactor) {
+        return compactor.getStringFromId(vcsRootId);
+    }
+
+    public Integer vcsRootInstanceId() {
+        return vcsRootInstanceId < 0 ? null : vcsRootInstanceId;
+    }
+
+    /**
+     *
+     */
+    public String commitFullVersion() {
+        if (version == null)
+            return "";
+
+        return DatatypeConverter.printHexBinary(version).toLowerCase();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (o == null || getClass() != o.getClass())
+            return false;
+        RevisionCompacted compacted = (RevisionCompacted)o;
+        return _ver == compacted._ver &&
+            vcsBranchName == compacted.vcsBranchName &&
+            vcsRootId == compacted.vcsRootId &&
+            vcsRootInstanceId == compacted.vcsRootInstanceId &&
+            Arrays.equals(version, compacted.version);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = Objects.hash(_ver, vcsBranchName, vcsRootId, vcsRootInstanceId);
+        res = 31 * res + Arrays.hashCode(version);
+        return res;
+    }
+}
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 8606a71..d413643 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,9 +17,16 @@
 package org.apache.ignite.ci.teamcity.ignited.fatbuild;
 
 import com.google.common.base.MoreObjects;
-import com.google.common.base.Objects;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collections;
 import java.util.Date;
+import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicBoolean;
+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;
@@ -32,20 +39,17 @@ import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrenceFull;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrencesFull;
 import org.apache.ignite.ci.tcmodel.user.User;
+import org.apache.ignite.ci.tcmodel.vcs.Revision;
+import org.apache.ignite.ci.tcmodel.vcs.Revisions;
+import org.apache.ignite.ci.tcmodel.vcs.VcsRootInstance;
 import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
 import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
+import org.apache.ignite.ci.teamcity.ignited.change.RevisionCompacted;
 import org.apache.ignite.ci.teamcity.ignited.runhist.Invocation;
 import org.apache.ignite.ci.teamcity.ignited.runhist.InvocationData;
 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;
-
 /**
  * Composed data from {@link Build} and other classes, compressed for storage.
  */
@@ -110,6 +114,8 @@ public class FatBuildCompacted extends BuildRefCompacted implements IVersionedEn
 
     @Nullable private TriggeredCompacted triggered;
 
+    @Nullable private RevisionCompacted revisions[];
+
     /** {@inheritDoc} */
     @Override public int version() {
         return _ver;
@@ -192,6 +198,15 @@ public class FatBuildCompacted extends BuildRefCompacted implements IVersionedEn
 
             triggered.buildId = trigBuildRef != null ? trigBuildRef.getId() : -1;
         }
+
+        Revisions revisions = build.getRevisions();
+        if(revisions!=null) {
+            this.revisions = revisions.revisions()
+                .stream()
+                .filter(b -> b.version() != null)
+                .map(revision -> new RevisionCompacted(compactor, revision))
+                .toArray(RevisionCompacted[]::new);
+        }
     }
 
     public FatBuildCompacted setFakeStub(boolean val) {
@@ -289,6 +304,25 @@ public class FatBuildCompacted extends BuildRefCompacted implements IVersionedEn
             res.setTriggered(trigXml);
         }
 
+        if (revisions != null) {
+            List<RevisionCompacted> revs = Arrays.asList(revisions);
+            res.setRevisions(revs.stream().map(revComp -> {
+                Revision revision = new Revision()
+                    .version(revComp.commitFullVersion())
+                    .vcsBranchName(revComp.vcsBranchName(compactor));
+
+                String vcsRootId = revComp.vcsRootId(compactor);
+                Integer vcsRootInstanceId = revComp.vcsRootInstanceId();
+
+                if (vcsRootId == null && vcsRootInstanceId == null)
+                    return revision;
+
+                return revision.vcsRootInstance(
+                    new VcsRootInstance()
+                        .id(vcsRootInstanceId)
+                        .vcsRootId(vcsRootId));
+            }).collect(Collectors.toList()));
+        }
     }
 
     /**
@@ -377,18 +411,23 @@ public class FatBuildCompacted extends BuildRefCompacted implements IVersionedEn
             queuedDate == that.queuedDate &&
             projectId == that.projectId &&
             name == that.name &&
-            Objects.equal(tests, that.tests) &&
-            Objects.equal(snapshotDeps, that.snapshotDeps) &&
-            Objects.equal(flags, that.flags) &&
-                Objects.equal(problems, that.problems) &&
-                Objects.equal(statistics, that.statistics)
-                && Objects.equal(changesIds, that.changesIds);
+            Objects.equals(tests, that.tests) &&
+            Arrays.equals(snapshotDeps, that.snapshotDeps) &&
+            Objects.equals(flags, that.flags) &&
+            Objects.equals(problems, that.problems) &&
+            Objects.equals(statistics, that.statistics) &&
+            Arrays.equals(changesIds, that.changesIds) &&
+            Objects.equals(triggered, that.triggered) &&
+            Arrays.equals(revisions, that.revisions);
     }
 
     /** {@inheritDoc} */
     @Override public int hashCode() {
-        return Objects.hashCode(super.hashCode(), _ver, startDate, finishDate, queuedDate, projectId, name, tests,
-                snapshotDeps, flags, problems, statistics, changesIds);
+        int res = Objects.hash(super.hashCode(), _ver, startDate, finishDate, queuedDate, projectId, name, tests, flags, problems, statistics, triggered);
+        res = 31 * res + Arrays.hashCode(snapshotDeps);
+        res = 31 * res + Arrays.hashCode(changesIds);
+        res = 31 * res + Arrays.hashCode(revisions);
+        return res;
     }
 
     /**
@@ -516,6 +555,7 @@ public class FatBuildCompacted extends BuildRefCompacted implements IVersionedEn
         return snapshotDeps.clone();
     }
 
+    /** {@inheritDoc} */
     @Override public String toString() {
         return MoreObjects.toStringHelper(this)
             .add("_", super.toString())
@@ -532,6 +572,7 @@ public class FatBuildCompacted extends BuildRefCompacted implements IVersionedEn
             .add("statistics", statistics)
             .add("changesIds", changesIds)
             .add("triggered", triggered)
+            .add("revisions", revisions)
             .toString();
     }
 
@@ -572,4 +613,14 @@ public class FatBuildCompacted extends BuildRefCompacted implements IVersionedEn
         return this;
     }
 
+    /**
+     * @return revisions list or null if revisions was not reported by TC/for older build versions in DB.
+     */
+    @Nullable
+    public List<RevisionCompacted> revisions() {
+        if (revisions == null)
+            return null;
+
+        return Collections.unmodifiableList(Arrays.asList(revisions));
+    }
 }
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 1f5087e..04964fd 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
@@ -63,6 +63,8 @@ import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
 import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrences;
 import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrencesFull;
+import org.apache.ignite.ci.tcmodel.vcs.Revision;
+import org.apache.ignite.ci.tcmodel.vcs.Revisions;
 import org.apache.ignite.ci.teamcity.ignited.buildref.BuildRefDao;
 import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeRefCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
@@ -513,6 +515,23 @@ public class IgnitedTcInMemoryIntegrationTest {
         int[] ch = buildCompacted.changes();
 
         assertEquals(6, ch.length);
+
+        final Revisions refRevisions = refBuild.getRevisions();
+        final Revisions actRevisions = actBuild.getRevisions();
+        assertNotNull(refRevisions);
+        assertNotNull(actRevisions);
+
+        Set<String> refVersions = refRevisions.revisions().stream().map(Revision::version).collect(Collectors.toSet());
+        Set<String> actVersions = actRevisions.revisions().stream().map(Revision::version).collect(Collectors.toSet());
+
+        assertEquals(refVersions, actVersions);
+
+        Revision refRev0 = refRevisions.revisions().get(0);
+        Revision actRev0 = actRevisions.revisions().get(0);
+
+        assertEquals(refRev0.vcsBranchName(), actRev0.vcsBranchName());
+        assertEquals(refRev0.vcsRootInstance().id(), actRev0.vcsRootInstance().id());
+        assertEquals(refRev0.vcsRootInstance().vcsRootId(), actRev0.vcsRootInstance().vcsRootId());
     }
 
     private void saveTmpFile(Object obj, String name) throws IOException, JAXBException {