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

mpochatkin pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 6d85659dc41 IGNITE-15373 Add Kotlin DSL pipelines (#6583)
6d85659dc41 is described below

commit 6d85659dc41fa1a3544f338f21376cec0bf11e68
Author: Artem Egorov <[email protected]>
AuthorDate: Fri Nov 7 11:02:05 2025 +0200

    IGNITE-15373 Add Kotlin DSL pipelines (#6583)
---
 .teamcity/.gitignore                               |   5 +
 .teamcity/_Self/Project.kt                         |  26 ++
 .teamcity/build/Project.kt                         |  37 +++
 .teamcity/build/build_types/ApacheIgnite3.kt       |  26 ++
 .teamcity/build/build_types/ReleaseBuild.kt        | 147 ++++++++
 .teamcity/build/distributions/CliDeb.kt            |  28 ++
 .teamcity/build/distributions/CliRpm.kt            |  24 ++
 .teamcity/build/distributions/Deb.kt               |  21 ++
 .teamcity/build/distributions/Docs.kt              |  18 +
 .../build/distributions/DotnetBinariesDocs.kt      |  54 +++
 .teamcity/build/distributions/JavaBinariesDocs.kt  |  29 ++
 .teamcity/build/distributions/MigrationToolsZip.kt |  21 ++
 .teamcity/build/distributions/OdbcDeb.kt           |  57 ++++
 .teamcity/build/distributions/OdbcRpm.kt           |  74 +++++
 .teamcity/build/distributions/OdbcZip.kt           |  66 ++++
 .teamcity/build/distributions/OpenapiSpec.kt       |  18 +
 .teamcity/build/distributions/Project.kt           |  37 +++
 .teamcity/build/distributions/Rpm.kt               |  21 ++
 .teamcity/build/distributions/Zip.kt               |  22 ++
 .teamcity/files/scripts/bash/CheckCodeBase.sh      |  15 +
 .../files/scripts/bash/CheckInternalPackages.sh    |   7 +
 .../scripts/bash/CleanUpLocalMavenRepository.sh    |   1 +
 .../scripts/bash/CleanUpRemainingProcesses.sh      |  53 +++
 .teamcity/files/scripts/bash/DockerImagePrune.sh   |   1 +
 .../teamcity/ApacheIgnite3CustomBuildType.kt       |  54 +++
 .../ignite/teamcity/ApacheIgnite3Teamcity.kt       | 370 +++++++++++++++++++++
 .../org/apache/ignite/teamcity/CustomBuildSteps.kt |  93 ++++++
 .../org/apache/ignite/teamcity/CustomBuildType.kt  | 104 ++++++
 .../ignite/teamcity/CustomFailureConditions.kt     |  27 ++
 .../org/apache/ignite/teamcity/CustomTriggers.kt   |  99 ++++++
 .teamcity/org/apache/ignite/teamcity/Teamcity.kt   | 121 +++++++
 .teamcity/pom.xml                                  | 104 ++++++
 .teamcity/settings.kts                             |  27 ++
 .teamcity/test/Project.kt                          |  77 +++++
 .teamcity/test/build_types/RunAllTests.kt          |  47 +++
 .teamcity/test/build_types/RunAllTestsCustomJDK.kt |  33 ++
 .teamcity/test/build_types/RunPlatformTests.kt     |  20 ++
 .teamcity/test/build_types/RunSanityCheck.kt       |  22 ++
 .teamcity/test/integration_tests/Project.kt        |  16 +
 .../test/platform_tests/PlatformCppTestsLinux.kt   | 153 +++++++++
 .../test/platform_tests/PlatformCppTestsWindows.kt | 151 +++++++++
 .../platform_tests/PlatformDotnetTestsLinux.kt     | 100 ++++++
 .../platform_tests/PlatformDotnetTestsWindows.kt   |  94 ++++++
 .../platform_tests/PlatformPythonTestsLinux.kt     |  84 +++++
 .teamcity/test/platform_tests/Project.kt           |  44 +++
 .teamcity/test/sanity_check/Project.kt             |  27 ++
 .../build_types/AssembleTestClassesJdk11.kt        |  20 ++
 .../test/sanity_check/build_types/CodeStyle.kt     |  37 +++
 .teamcity/test/sanity_check/build_types/Javadoc.kt |  36 ++
 .../test/sanity_check/build_types/MentionTicket.kt |  26 ++
 .teamcity/test/sanity_check/build_types/PMD.kt     |  22 ++
 .../test/sanity_check/build_types/Spotbugs.kt      |  19 ++
 .teamcity/test/template_types/GradleModule.kt      |   9 +
 .teamcity/test/template_types/OtherTestsModule.kt  |  64 ++++
 .teamcity/test/template_types/RunTests.kt          |  22 ++
 .teamcity/test/template_types/RunTestsList.kt      |  21 ++
 .teamcity/test/template_types/TestConfiguration.kt |   9 +
 .teamcity/test/template_types/Tests.kt             |  33 ++
 .teamcity/test/template_types/TestsModule.kt       |  66 ++++
 .teamcity/test/unit_tests/Project.kt               |  13 +
 build.gradle                                       |  17 +-
 61 files changed, 3084 insertions(+), 5 deletions(-)

diff --git a/.teamcity/.gitignore b/.teamcity/.gitignore
new file mode 100644
index 00000000000..98607ad8d14
--- /dev/null
+++ b/.teamcity/.gitignore
@@ -0,0 +1,5 @@
+target/
+
+# Undo ignoring build directory
+!build/
+
diff --git a/.teamcity/_Self/Project.kt b/.teamcity/_Self/Project.kt
new file mode 100644
index 00000000000..9b6a7d4bf5f
--- /dev/null
+++ b/.teamcity/_Self/Project.kt
@@ -0,0 +1,26 @@
+package _Self
+
+import jetbrains.buildServer.configs.kotlin.DslContext
+import jetbrains.buildServer.configs.kotlin.Project
+import org.apache.ignite.teamcity.Teamcity.Companion.hiddenText
+
+/**
+ * Variable to separate main (production) project from development projects
+ */
+var isActiveProject: Boolean = DslContext.projectName == "[Apache Ignite 3.x]"
+
+object Project : Project({
+    subProject(build.Project)
+    subProject(test.Project)
+
+    /**
+     * Project-wide params
+     */
+    params {
+        hiddenText("system.lastCommitHash", "%build.vcs.number%")
+        hiddenText("IGNITE_CI", "true")
+        hiddenText("env.GRADLE_OPTS", "-Dorg.gradle.caching=true")
+        hiddenText("env.JAVA_HOME", "%env.JDK_ORA_17%")
+        hiddenText("env.M2_HOME", "%teamcity.tool.maven.DEFAULT%")
+    }
+})
diff --git a/.teamcity/build/Project.kt b/.teamcity/build/Project.kt
new file mode 100644
index 00000000000..5270de323b6
--- /dev/null
+++ b/.teamcity/build/Project.kt
@@ -0,0 +1,37 @@
+package build
+
+import build.build_types.ApacheIgnite3
+import build.build_types.ReleaseBuild
+import jetbrains.buildServer.configs.kotlin.Project
+import org.apache.ignite.teamcity.ApacheIgnite3CustomBuildType
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+
+
+object Project : Project({
+    id(getId(this::class))
+    name = "[Build]"
+
+    subProject(build.distributions.Project)
+
+    /**
+     * Pre-compiling ignite for consistent caching
+     */
+
+    buildType(
+        ApacheIgnite3CustomBuildType.Builder(ApacheIgnite3)
+            .ignite3VCS()
+            .defaultBuildTypeSettings().requireLinux()
+            .build().buildType
+    )
+
+    /**
+     * Aggregating pipeline that collects all distributions
+     */
+
+    buildType(
+        ApacheIgnite3CustomBuildType.Builder(ReleaseBuild)
+            .ignite3VCS().ignite3CommitStatusPublisher()
+            .defaultBuildTypeSettings().requireLinux()
+            .build().buildType
+    )
+})
diff --git a/.teamcity/build/build_types/ApacheIgnite3.kt 
b/.teamcity/build/build_types/ApacheIgnite3.kt
new file mode 100644
index 00000000000..a2ecc6c7ae1
--- /dev/null
+++ b/.teamcity/build/build_types/ApacheIgnite3.kt
@@ -0,0 +1,26 @@
+package build.build_types
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import jetbrains.buildServer.configs.kotlin.BuildStep
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customScript
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+
+
+object ApacheIgnite3 : BuildType({
+    id(getId(this::class))
+    name = "Apache Ignite 3"
+
+    steps {
+        customScript(type = "bash") {
+            name = "Clean up local maven repository"
+        }
+
+        customGradle {
+            name = "Build Apache Ignite 3"
+            tasks = "assemble integrationTestClasses testClasses"
+            executionMode = BuildStep.ExecutionMode.RUN_ON_FAILURE
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+})
diff --git a/.teamcity/build/build_types/ReleaseBuild.kt 
b/.teamcity/build/build_types/ReleaseBuild.kt
new file mode 100644
index 00000000000..471ff9bf182
--- /dev/null
+++ b/.teamcity/build/build_types/ReleaseBuild.kt
@@ -0,0 +1,147 @@
+package build.build_types
+
+import _Self.isActiveProject
+import build.distributions.*
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customScript
+import org.apache.ignite.teamcity.CustomTriggers.Companion.customSchedule
+import org.apache.ignite.teamcity.CustomTriggers.Companion.pullRequestChange
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+
+
+object ReleaseBuild : BuildType({
+    id(getId(this::class))
+    name = "[1] Release Build"
+    artifactRules = """
+        **/*
+        -: %VCSROOT__IGNITE3%
+    """.trimIndent()
+
+    triggers {
+        customSchedule(0, "+:<default>", enabled = isActiveProject) {}
+        pullRequestChange(enabled = isActiveProject) {
+            triggerRules = """
+                +:gradle/libs.versions.toml
+                +:gradle/**
+                +:packaging/**
+            """.trimIndent()
+            branchFilter = """
+                +:pull/*
+                +:dependabot/*
+            """.trimIndent()
+        }
+    }
+
+    steps {
+        customScript(type = "bash") {
+            name = "Clean up local maven repository"
+        }
+
+        customGradle {
+            name = "Install to local repository"
+            id = "Install_to_local_repository"
+            tasks = "publishToMavenLocal"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+
+    dependencies {
+        dependency(CliDeb) {
+            snapshot {}
+            artifacts {
+                cleanDestination = true
+                artifactRules = "cli-deb => ignite-cli-deb"
+            }
+        }
+        dependency(CliRpm) {
+            snapshot {}
+            artifacts {
+                cleanDestination = true
+                artifactRules = "cli-rpm => ignite-cli-rpm"
+            }
+        }
+        dependency(Deb) {
+            snapshot {}
+            artifacts {
+                cleanDestination = true
+                artifactRules = "deb => ignite-deb"
+            }
+        }
+        dependency(Docs) {
+            snapshot {}
+            artifacts {
+                artifactRules = "doxygen-cpp.zip => ignite-docs"
+            }
+        }
+        dependency(DotnetBinariesDocs) {
+            snapshot {}
+            artifacts {
+                cleanDestination = true
+                artifactRules = """
+                    nuget => ignite-nuget
+                    dotnet => ignite-dotnet
+                    dotnetdoc.zip => ignite-docs
+                """.trimIndent()
+            }
+        }
+        dependency(JavaBinariesDocs) {
+            snapshot {}
+            artifacts {
+                artifactRules = """
+                    javadoc.zip => ignite-docs
+                    libs.zip
+                """.trimIndent()
+            }
+        }
+        dependency(OdbcDeb) {
+            snapshot {}
+            artifacts {
+                cleanDestination = true
+                artifactRules = "odbc-deb => ignite-odbc-deb"
+            }
+        }
+        dependency(OdbcRpm) {
+            snapshot {}
+            artifacts {
+                cleanDestination = true
+                artifactRules = "odbc-rpm => ignite-odbc-rpm"
+            }
+        }
+        dependency(OdbcZip) {
+            snapshot {}
+            artifacts {
+                artifactRules = "odbc-zip => ignite-odbc-zip"
+            }
+        }
+        dependency(OpenapiSpec) {
+            snapshot {}
+            artifacts {
+                cleanDestination = true
+                artifactRules = "openapi.yaml => openapi"
+            }
+        }
+        dependency(Rpm) {
+            snapshot {}
+            artifacts {
+                cleanDestination = true
+                artifactRules = "rpm => ignite-rpm"
+            }
+        }
+        dependency(Zip) {
+            snapshot {}
+            artifacts {
+                cleanDestination = true
+                artifactRules = "zip => ignite-zip"
+            }
+        }
+        dependency(MigrationToolsZip) {
+            snapshot {}
+            artifacts {
+                cleanDestination = true
+                artifactRules = "migration-tools-cli-zip => 
migration-tools-cli"
+            }
+        }
+    }
+
+})
diff --git a/.teamcity/build/distributions/CliDeb.kt 
b/.teamcity/build/distributions/CliDeb.kt
new file mode 100644
index 00000000000..1280d140252
--- /dev/null
+++ b/.teamcity/build/distributions/CliDeb.kt
@@ -0,0 +1,28 @@
+package build.distributions
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import jetbrains.buildServer.configs.kotlin.ParameterDisplay
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+
+object CliDeb : BuildType({
+    name = "[4] CLI DEB"
+
+    artifactRules = """
+        %VCSROOT__IGNITE3%/packaging/cli/build/distributions/*.deb => cli-deb
+        %VCSROOT__IGNITE3%/packaging/cli/build/distributions/*.changes => 
cli-deb
+    """.trimIndent()
+
+    params {
+        text("DIR_BUILD", "deliveries/deb", display = ParameterDisplay.HIDDEN, 
allowEmpty = true)
+        text("DIR_BINARIES", "", display = ParameterDisplay.HIDDEN, allowEmpty 
= true)
+        text("DIR_PACKAGES", "", display = ParameterDisplay.HIDDEN, allowEmpty 
= true)
+    }
+
+    steps {
+        customGradle {
+            name = "Build DEB"
+            tasks = "packaging-cli:buildDeb"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+})
diff --git a/.teamcity/build/distributions/CliRpm.kt 
b/.teamcity/build/distributions/CliRpm.kt
new file mode 100644
index 00000000000..605f3bbbe6c
--- /dev/null
+++ b/.teamcity/build/distributions/CliRpm.kt
@@ -0,0 +1,24 @@
+package build.distributions
+
+import jetbrains.buildServer.configs.kotlin.*
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+
+object CliRpm : BuildType({
+    name = "[5] CLI RPM"
+
+    artifactRules = 
"%VCSROOT__IGNITE3%/packaging/cli/build/distributions/*.rpm => cli-rpm"
+
+    params {
+        text("DIR_BUILD", "deliveries/deb", display = ParameterDisplay.HIDDEN, 
allowEmpty = true)
+        text("DIR_BINARIES", "", display = ParameterDisplay.HIDDEN, allowEmpty 
= true)
+        text("DIR_PACKAGES", "", display = ParameterDisplay.HIDDEN, allowEmpty 
= true)
+    }
+
+    steps {
+        customGradle {
+            name = "Build RPM"
+            tasks = "packaging-cli:buildRpm"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+})
diff --git a/.teamcity/build/distributions/Deb.kt 
b/.teamcity/build/distributions/Deb.kt
new file mode 100644
index 00000000000..3a2a5393b58
--- /dev/null
+++ b/.teamcity/build/distributions/Deb.kt
@@ -0,0 +1,21 @@
+package build.distributions
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+
+object Deb : BuildType({
+    name = "[3] DEB"
+
+    artifactRules = """
+        %VCSROOT__IGNITE3%/packaging/db/build/distributions/*.deb => deb
+        %VCSROOT__IGNITE3%/packaging/db/build/distributions/*.changes => deb
+    """.trimIndent()
+
+    steps {
+        customGradle {
+            name = "Build DEB"
+            tasks = "packaging-db:buildDeb -Pplatforms.enable"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+})
diff --git a/.teamcity/build/distributions/Docs.kt 
b/.teamcity/build/distributions/Docs.kt
new file mode 100644
index 00000000000..213e8aa1cd7
--- /dev/null
+++ b/.teamcity/build/distributions/Docs.kt
@@ -0,0 +1,18 @@
+package build.distributions
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+
+object Docs : BuildType({
+    name = "[10] C++ Docs"
+    description = "Apache Ignite 3 OpenAPI specification"
+
+    artifactRules = "%VCSROOT__IGNITE3%/modules/platforms/cpp/docs/html/ => 
doxygen-cpp.zip"
+
+    steps {
+        customGradle {
+            tasks = "doxygenCppClient"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+})
diff --git a/.teamcity/build/distributions/DotnetBinariesDocs.kt 
b/.teamcity/build/distributions/DotnetBinariesDocs.kt
new file mode 100644
index 00000000000..cac802849e0
--- /dev/null
+++ b/.teamcity/build/distributions/DotnetBinariesDocs.kt
@@ -0,0 +1,54 @@
+package build.distributions
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import jetbrains.buildServer.configs.kotlin.ParameterDisplay
+import jetbrains.buildServer.configs.kotlin.buildFeatures.nuGetPackagesIndexer
+import jetbrains.buildServer.configs.kotlin.buildSteps.dotnetPack
+import jetbrains.buildServer.configs.kotlin.buildSteps.dotnetPublish
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+
+
+object DotnetBinariesDocs : BuildType({
+    name = "[1] .NET Binaries | Docs"
+
+    artifactRules = """
+        %DIR__DOTNET% => %DIR__DOTNET%
+        %DIR__NUGET% => %DIR__NUGET%
+        +:%VCSROOT__IGNITE3%/modules/platforms/dotnet/docs => dotnetdoc.zip
+    """.trimIndent()
+
+    params {
+        text("DIR__DOTNET", "dotnet", display = ParameterDisplay.HIDDEN, 
allowEmpty = true)
+        text("DIR__NUGET", "nuget", display = ParameterDisplay.HIDDEN, 
allowEmpty = true)
+    }
+
+    steps {
+        dotnetPublish {
+            name = "Build binaries"
+            projects = "Apache.Ignite.sln"
+            workingDir = "%VCSROOT__IGNITE3%/modules/platforms/dotnet"
+            configuration = "Release"
+            outputDir = "%teamcity.build.checkoutDir%/%DIR__DOTNET%"
+        }
+        dotnetPack {
+            name = "Build Nuget"
+            projects = "Apache.Ignite.sln"
+            workingDir = "%VCSROOT__IGNITE3%/modules/platforms/dotnet"
+            configuration = "Release"
+            outputDir = "%teamcity.build.checkoutDir%/%DIR__NUGET%"
+            args = "--include-source"
+        }
+        customGradle {
+            name = "Build docfx"
+            id = "Build_docfx"
+            tasks = "docfx"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+
+    features {
+        nuGetPackagesIndexer {
+            feed = "ignite3/ReleaseCandidate"
+        }
+    }
+})
diff --git a/.teamcity/build/distributions/JavaBinariesDocs.kt 
b/.teamcity/build/distributions/JavaBinariesDocs.kt
new file mode 100644
index 00000000000..59e17f96eb8
--- /dev/null
+++ b/.teamcity/build/distributions/JavaBinariesDocs.kt
@@ -0,0 +1,29 @@
+package build.distributions
+
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+
+object JavaBinariesDocs : BuildType({
+    name = "[1] Java Binaries | Docs"
+
+    artifactRules = """
+        +:%VCSROOT__IGNITE3%/build/docs => javadoc.zip
+        +:%VCSROOT__IGNITE3%/modules/*/build/libs/** => libs.zip
+        +:%VCSROOT__IGNITE3%/modules/jdbc/build/libs/*-all.jar => ignite-jdbc
+    """.trimIndent()
+
+    steps {
+        customGradle {
+            name = "Build | Assemble binaries"
+            tasks = "jar shadowJar"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+        customGradle {
+            name = "Aggregate Javadocs"
+            id = "gradle_runner"
+            tasks = "aggregateJavadoc"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+})
diff --git a/.teamcity/build/distributions/MigrationToolsZip.kt 
b/.teamcity/build/distributions/MigrationToolsZip.kt
new file mode 100644
index 00000000000..0305e0e9388
--- /dev/null
+++ b/.teamcity/build/distributions/MigrationToolsZip.kt
@@ -0,0 +1,21 @@
+package build.distributions
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+
+object MigrationToolsZip : BuildType({
+    name = "Migration Tools CLI ZIP"
+
+    artifactRules = """
+        
%VCSROOT__IGNITE3%/migration-tools/packaging/cli/build/distributions/*.zip => 
migration-tools-cli-zip
+        -:**/tmp/** => zip
+    """.trimIndent()
+
+    steps {
+        customGradle {
+            name = "Build Migration Tools ZIP"
+            tasks = "migration-tools-packaging-cli:distZip"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+})
diff --git a/.teamcity/build/distributions/OdbcDeb.kt 
b/.teamcity/build/distributions/OdbcDeb.kt
new file mode 100644
index 00000000000..10e71093793
--- /dev/null
+++ b/.teamcity/build/distributions/OdbcDeb.kt
@@ -0,0 +1,57 @@
+package build.distributions
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import jetbrains.buildServer.configs.kotlin.buildSteps.script
+
+object OdbcDeb : BuildType({
+    name = "[7] ODBC Deb package"
+    description = "Apache Ignite 3 ODBC Deb Package"
+
+    artifactRules = """
+        %VCSROOT__IGNITE3%/packaging/odbc/build/distributions/*.deb => odbc-deb
+        %VCSROOT__IGNITE3%/packaging/odbc/build/distributions/*.changes => 
odbc-deb
+    """.trimIndent()
+
+    steps {
+        script {
+            name = "Install Conan"
+            enabled = false
+            scriptContent = """
+                pip install wheel || exit 0
+                pip install -v "conan>=1.56.0,<2.0.0" --force-reinstall  || 
exit 1
+                
+                ln -s /opt/buildagent/.local/bin/conan conan
+            """.trimIndent()
+        }
+        script {
+            name = "Check env"
+            scriptContent = """
+                gcc --version || exit 0
+                g++ --version || exit 0
+                
+                odbcinst -j || exit 0
+                cat /etc/odbcinst.ini || exit 0
+                
+                conan --version
+                conan profile list
+                conan profile show default || exit 0
+                
+                conan info --path . || exit 0
+            """.trimIndent()
+        }
+        customGradle {
+            name = "Build Deb"
+            tasks = ":packaging-odbc:buildDeb -i -Pplatforms.enable"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+
+    /**
+     *  Temporary lock ODBC jobs on old-type agents
+     *  until execution of the :platforms:cmakeBuildOdbc target is fixed on 
DIND agents
+     */
+    requirements {
+        doesNotExist("env.DIND_ENABLED")
+    }
+})
diff --git a/.teamcity/build/distributions/OdbcRpm.kt 
b/.teamcity/build/distributions/OdbcRpm.kt
new file mode 100644
index 00000000000..a485d5501f9
--- /dev/null
+++ b/.teamcity/build/distributions/OdbcRpm.kt
@@ -0,0 +1,74 @@
+package build.distributions
+
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import jetbrains.buildServer.configs.kotlin.buildSteps.ExecBuildStep
+import jetbrains.buildServer.configs.kotlin.buildSteps.exec
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import jetbrains.buildServer.configs.kotlin.buildSteps.script
+
+object OdbcRpm : BuildType({
+    name = "[8] ODBC RPM package"
+    description = "Apache Ignite 3 ODBC RPM package"
+
+    artifactRules = 
"%VCSROOT__IGNITE3%/packaging/odbc/build/distributions/*.rpm=> odbc-rpm"
+
+    params {
+        param("CONTAINER_JAVA_HOME", "/usr/lib/jvm/java-17-openjdk/")
+    }
+
+    steps {
+        script {
+            name = "Check env"
+            scriptContent = """
+                gcc --version || exit 0
+                g++ --version || exit 0
+                
+                odbcinst -j || exit 0
+                cat /etc/odbcinst.ini || exit 0
+                
+                conan --version
+                conan profile list
+                conan profile show default || exit 0
+                
+                conan info --path . || exit 0
+            """.trimIndent()
+        }
+
+        customGradle {
+            tasks = ":packaging-odbc:buildRpm -i -Pplatforms.enable"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+
+        script {
+            name = "[HACK] Set AGENT_NUMBER"
+            id = "HACK_Set_AGENT_NUMBER"
+            enabled = false
+            scriptContent = """
+                AGENT_NUMBER=${'$'}(echo %system.agent.name% | tail -c 3)
+                echo "##teamcity[setParameter name='AGENT_NUMBER' 
value='${'$'}{AGENT_NUMBER}']"
+            """.trimIndent()
+        }
+
+        exec {
+            name = "Build ODBC RPM (Under Rocky Linux 8 container)"
+            id = "Build_ODBC_RPM_Under_Rocky_Linux_8_container"
+            enabled = false
+            path = "./gradlew"
+            arguments = ":packaging-odbc:buildRpm -i -Pplatforms.enable"
+            dockerImage = "ggshared/tc-agent:rockylinux_latest"
+            dockerImagePlatform = ExecBuildStep.ImagePlatform.Linux
+            dockerPull = true
+            dockerRunParameters = "-e JAVA_HOME=%CONTAINER_JAVA_HOME% -v 
/mnt/teamcity/%AGENT_NUMBER%/work/%teamcity.build.default.checkoutDir%:%teamcity.build.checkoutDir%"
+            param("script.content", "./gradlew")
+        }
+    }
+
+    /**
+     *  Temporary lock ODBC jobs on old-type agents
+     *  until execution of the :platforms:cmakeBuildOdbc target is fixed on 
DIND agents
+     */
+    requirements {
+        doesNotExist("env.DIND_ENABLED")
+    }
+})
diff --git a/.teamcity/build/distributions/OdbcZip.kt 
b/.teamcity/build/distributions/OdbcZip.kt
new file mode 100644
index 00000000000..bf3a5e6e7d3
--- /dev/null
+++ b/.teamcity/build/distributions/OdbcZip.kt
@@ -0,0 +1,66 @@
+package build.distributions
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import jetbrains.buildServer.configs.kotlin.buildSteps.script
+
+object OdbcZip : BuildType({
+    name = "[9] ODBC Zip package"
+    description = "Apache Ignite 3 ODBC Deb Package"
+
+    artifactRules = """
+        %VCSROOT__IGNITE3%/packaging/odbc/build/distributions/*.zip => odbc-zip
+        %VCSROOT__IGNITE3%/packaging/odbc/build/distributions/*.tar => odbc-zip
+    """.trimIndent()
+
+    steps {
+        script {
+            name = "Install Conan"
+            enabled = false
+            scriptContent = """
+                pip install wheel || exit 0
+                pip install -v "conan>=1.56.0,<2.0.0" --force-reinstall  || 
exit 1
+                
+                ln -s /opt/buildagent/.local/bin/conan conan
+            """.trimIndent()
+        }
+
+        script {
+            name = "Check env"
+            scriptContent = """
+                gcc --version || exit 0
+                g++ --version || exit 0
+                
+                odbcinst -j || exit 0
+                cat /etc/odbcinst.ini || exit 0
+                
+                conan --version
+                conan profile list
+                conan profile show default || exit 0
+                
+                conan info --path . || exit 0
+            """.trimIndent()
+        }
+
+        customGradle {
+            name = "Build Zip"
+            tasks = ":packaging-odbc:distZip -i -Pplatforms.enable"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+
+        customGradle {
+            name = "Build Tar"
+            id = "Build_Tar"
+            tasks = ":packaging-odbc:distTar -i -Pplatforms.enable"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+
+    /**
+     *  Temporary lock ODBC jobs on old-type agents
+     *  until execution of the :platforms:cmakeBuildOdbc target is fixed on 
DIND agents
+     */
+    requirements {
+        doesNotExist("env.DIND_ENABLED")
+    }
+})
diff --git a/.teamcity/build/distributions/OpenapiSpec.kt 
b/.teamcity/build/distributions/OpenapiSpec.kt
new file mode 100644
index 00000000000..b21b7381fac
--- /dev/null
+++ b/.teamcity/build/distributions/OpenapiSpec.kt
@@ -0,0 +1,18 @@
+package build.distributions
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+
+object OpenapiSpec : BuildType({
+    name = "[10] OpenAPI specification"
+    description = "Apache Ignite 3 OpenAPI specification"
+
+    artifactRules = 
"%VCSROOT__IGNITE3%/modules/rest-api/build/openapi/openapi.yaml => openapi.yaml"
+
+    steps {
+        customGradle {
+            tasks = ":ignite-rest-api:compileJava"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+})
diff --git a/.teamcity/build/distributions/Project.kt 
b/.teamcity/build/distributions/Project.kt
new file mode 100644
index 00000000000..05984937d75
--- /dev/null
+++ b/.teamcity/build/distributions/Project.kt
@@ -0,0 +1,37 @@
+package build.distributions
+
+import jetbrains.buildServer.configs.kotlin.Project
+import org.apache.ignite.teamcity.ApacheIgnite3CustomBuildType
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+
+object Project : Project({
+    id(getId(this::class))
+    name = "[Distributions]"
+
+    /**
+     * Full list of all product distributions
+     */
+
+    listOf(
+        CliDeb,
+        CliRpm,
+        Deb,
+        Docs,
+        DotnetBinariesDocs,
+        JavaBinariesDocs,
+        OdbcDeb,
+        OdbcRpm,
+        OdbcZip,
+        OpenapiSpec,
+        Rpm,
+        Zip,
+        MigrationToolsZip
+    ).forEach {
+        buildType(
+            ApacheIgnite3CustomBuildType.Builder(it)
+                .ignite3VCS().ignite3BuildDependency()
+                .defaultBuildTypeSettings().requireLinux()
+                .build().buildType
+        )
+    }
+})
diff --git a/.teamcity/build/distributions/Rpm.kt 
b/.teamcity/build/distributions/Rpm.kt
new file mode 100644
index 00000000000..81ec687e0b9
--- /dev/null
+++ b/.teamcity/build/distributions/Rpm.kt
@@ -0,0 +1,21 @@
+package build.distributions
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+
+object Rpm : BuildType({
+    name = "[2] RPM"
+
+    artifactRules = """
+        %VCSROOT__IGNITE3%/packaging/cli/build/distributions/*.rpm => rpm
+        %VCSROOT__IGNITE3%/packaging/db/build/distributions/*.rpm => rpm
+    """.trimIndent()
+
+    steps {
+        customGradle {
+            name = "Build RPM"
+            tasks = "packaging-db:buildRpm -Pplatforms.enable"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+})
diff --git a/.teamcity/build/distributions/Zip.kt 
b/.teamcity/build/distributions/Zip.kt
new file mode 100644
index 00000000000..2f71c6957ea
--- /dev/null
+++ b/.teamcity/build/distributions/Zip.kt
@@ -0,0 +1,22 @@
+package build.distributions
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+
+object Zip : BuildType({
+    name = "[6] All Zip"
+
+    artifactRules = """
+        %VCSROOT__IGNITE3%/packaging/db/build/distributions/*.zip => zip
+        %VCSROOT__IGNITE3%/packaging/cli/build/distributions/*.zip => zip
+        -:**/tmp/** => zip
+    """.trimIndent()
+
+    steps {
+        customGradle {
+            name = "Build ZIP"
+            tasks = "allDistZip -Pplatforms.enable"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+})
diff --git a/.teamcity/files/scripts/bash/CheckCodeBase.sh 
b/.teamcity/files/scripts/bash/CheckCodeBase.sh
new file mode 100644
index 00000000000..6816416bf4a
--- /dev/null
+++ b/.teamcity/files/scripts/bash/CheckCodeBase.sh
@@ -0,0 +1,15 @@
+TRIGGER=%teamcity.build.branch%
+
+if echo $TRIGGER | grep pull; then
+  PR=${TRIGGER#*/}
+  SOURCE=$(curl -s https://api.github.com/repos/apache/ignite-3/pulls/$PR | jq 
-r .head.ref)
+else
+  SOURCE=$TRIGGER
+fi
+echo $SOURCE
+
+if grep -IER --exclude-dir={.git,.idea} '.' -e ".*${SOURCE}.*"; then
+    echo
+    echo "Code base contains mention ticket!"
+    echo
+fi
\ No newline at end of file
diff --git a/.teamcity/files/scripts/bash/CheckInternalPackages.sh 
b/.teamcity/files/scripts/bash/CheckInternalPackages.sh
new file mode 100644
index 00000000000..d1496a98dd0
--- /dev/null
+++ b/.teamcity/files/scripts/bash/CheckInternalPackages.sh
@@ -0,0 +1,7 @@
+PACKAGES="$(cat target/site/apidocs/index.html | grep org.apache.ignite | sed 
-r 's|.*html">(.*)</a.*|\1|' | grep internal || true)"
+if [ "${PACKAGES}" != "" ]; then
+       echo "[ERROR] Internal packages detected"
+    for package in ${PACKAGES}; do
+       echo "    ${package}"
+    done
+fi
\ No newline at end of file
diff --git a/.teamcity/files/scripts/bash/CleanUpLocalMavenRepository.sh 
b/.teamcity/files/scripts/bash/CleanUpLocalMavenRepository.sh
new file mode 100644
index 00000000000..c549c139c59
--- /dev/null
+++ b/.teamcity/files/scripts/bash/CleanUpLocalMavenRepository.sh
@@ -0,0 +1 @@
+rm -rfv ~/.m2/repository/org/apache/ignite
diff --git a/.teamcity/files/scripts/bash/CleanUpRemainingProcesses.sh 
b/.teamcity/files/scripts/bash/CleanUpRemainingProcesses.sh
new file mode 100644
index 00000000000..4245a014f93
--- /dev/null
+++ b/.teamcity/files/scripts/bash/CleanUpRemainingProcesses.sh
@@ -0,0 +1,53 @@
+# Pre-clean info
+echo "JPS (before): "
+sudo %env.JAVA_HOME%/bin/jps | while read -r process; do
+    echo "    ${process}"
+done
+echo
+
+echo "Killing processes starters by name"
+for processName in MainWithArgsInFile \
+                   IgniteNodeRunner \
+                   PlatformTestNodeRunner \
+                   CommandLineStartup \
+                   GradleDaemon; do
+    for PID in $(%env.JAVA_HOME%/bin/jps | grep ${processName} | awk '{ print 
$1 }'); do
+        echo -n "    Killing '${processName}' process with PID '${PID}'... "
+        processInfo="$(ps aux -p "$PID")"
+        sudo kill -9 "${PID}" && echo "[OK]" || {
+            echo "[ERROR] Unable to kill process ${PID}"
+            exit 1
+        }
+        echo "        Killed process info: ${processInfo}"
+    done
+done
+echo
+
+echo "Killing processes starters by port"
+for processPort in {3344..3345} \
+                   {10000..10050} \
+                   {10800..10850}; do
+    for PID in $(lsof -t -i:${processPort}); do
+        echo -n "    Killing  PID ${PID}"
+        processInfo="$(ps -L "$PID")"
+        kill -9 "${PID}"
+        echo "        Killed process info: ${processInfo}"
+    done
+done
+
+while read string; do
+    pid="$(cut -d" " -f1 <<< "${string}")"
+    process_name="$(cut -d" " -f5- <<< "${string}")"
+    echo "Kill $process_name with $pid PID"
+    kill -9 ${pid}
+done < <(ps a | grep '[b]in/java' | grep -v '/opt/java/openjdk/bin/java' | tr 
-s ' ' || true)
+
+# Post-clean info
+echo "JPS (after): "
+sudo %env.JAVA_HOME%/bin/jps | while read -r process; do
+    echo "    ${process}"
+done
+echo
+
+# Force correct permissions
+sudo chown -R teamcity:teamcity .
\ No newline at end of file
diff --git a/.teamcity/files/scripts/bash/DockerImagePrune.sh 
b/.teamcity/files/scripts/bash/DockerImagePrune.sh
new file mode 100644
index 00000000000..62d505a6e95
--- /dev/null
+++ b/.teamcity/files/scripts/bash/DockerImagePrune.sh
@@ -0,0 +1 @@
+docker image prune -f
\ No newline at end of file
diff --git 
a/.teamcity/org/apache/ignite/teamcity/ApacheIgnite3CustomBuildType.kt 
b/.teamcity/org/apache/ignite/teamcity/ApacheIgnite3CustomBuildType.kt
new file mode 100644
index 00000000000..d29ebc4cf69
--- /dev/null
+++ b/.teamcity/org/apache/ignite/teamcity/ApacheIgnite3CustomBuildType.kt
@@ -0,0 +1,54 @@
+package org.apache.ignite.teamcity
+
+import build.build_types.ApacheIgnite3
+import jetbrains.buildServer.configs.kotlin.AbsoluteId
+import jetbrains.buildServer.configs.kotlin.BuildType
+import jetbrains.buildServer.configs.kotlin.FailureAction
+import jetbrains.buildServer.configs.kotlin.buildFeatures.commitStatusPublisher
+import org.apache.ignite.teamcity.Teamcity.Companion.hiddenText
+
+
+class ApacheIgnite3CustomBuildType(override val buildType: BuildType) : 
CustomBuildType(buildType) {
+    class Builder(override var buildType: BuildType) : 
CustomBuildType.Builder(buildType) {
+        /**
+         * Apache Ignite 3 VCS settings
+         */
+        fun ignite3VCS() = apply {
+            buildType.params {
+                hiddenText("VCSROOT__IGNITE3", "ignite-3")
+                hiddenText("env.JAVA_HOME", "%env.JDK_ORA_11%")
+            }
+            buildType.vcs {
+                root(AbsoluteId("GitHubApacheIgnite3"), "+:. => 
%VCSROOT__IGNITE3%")
+            }
+        }
+
+        /**
+         * Send build status to Apache Ignite 3 GitHub repository
+         */
+        fun ignite3CommitStatusPublisher() = apply {
+            buildType.features {
+                commitStatusPublisher {
+                    vcsRootExtId = "GitHubApacheIgnite3"
+                    publisher = github {
+                        githubUrl = "https://api.github.com";
+                        authType = personalToken {
+                            token = 
"credentialsJSON:50faa412-ea0f-47ea-964c-f0cc77083d50"
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * Use pre-built Apache Ignite 3 artifacts instead of rebuilding 
project again
+         */
+        fun ignite3BuildDependency() = apply {
+            buildType.dependencies {
+                snapshot(ApacheIgnite3) {
+                    onDependencyFailure = FailureAction.FAIL_TO_START
+                }
+            }
+        }
+    }
+}
diff --git a/.teamcity/org/apache/ignite/teamcity/ApacheIgnite3Teamcity.kt 
b/.teamcity/org/apache/ignite/teamcity/ApacheIgnite3Teamcity.kt
new file mode 100644
index 00000000000..eee5e3aa8e9
--- /dev/null
+++ b/.teamcity/org/apache/ignite/teamcity/ApacheIgnite3Teamcity.kt
@@ -0,0 +1,370 @@
+package org.apache.ignite.teamcity
+
+import test.template_types.GradleModule
+import test.template_types.RunTests
+import test.template_types.TestConfiguration
+import test.template_types.Tests
+
+
+class ApacheIgnite3Teamcity {
+    companion object {
+        /*************
+         * CONSTANTS *
+         *************/
+
+        /**
+         * Project GradleModules with settings
+         */
+        private val IGNITE__ARCH_TEST = GradleModule(
+            "Arch",
+            "ignite-arch-test"
+        )
+        private val IGNITE__API = GradleModule(
+            "API",
+            "ignite-api"
+        )
+        private val IGNITE__BINARY_TUPLE = GradleModule(
+            "Binary Tuple",
+            "ignite-binary-tuple"
+        )
+        private val IGNITE__CATALOG = GradleModule(
+            "Catalog",
+            "ignite-catalog"
+        )
+        private val IGNITE__CLI = GradleModule(
+            "CLI",
+            "ignite-cli"
+        )
+        private val IGNITE__CLIENT = GradleModule(
+            "Client",
+            "ignite-client"
+        )
+        private val IGNITE__CLIENT_COMMON = GradleModule(
+            "Client Common",
+            "ignite-client-common"
+        )
+        private val IGNITE__CLIENT_HANDLER = GradleModule(
+            "Client Handler",
+            "ignite-client-handler"
+        )
+        private val IGNITE__CLUSTER_MANAGEMENT = GradleModule(
+            "Cluster Management",
+            "ignite-cluster-management"
+        )
+        private val IGNITE__CODE_DEPLOYMENT = GradleModule(
+            "Code Deployment",
+            "ignite-code-deployment"
+        )
+        private val IGNITE__COMPUTE = GradleModule(
+            "Compute",
+            "ignite-compute"
+        )
+        private val IGNITE__CONFIGURATION = GradleModule(
+            "Configuration",
+            "ignite-configuration"
+        )
+        private val IGNITE__CONFIGURATION_ANNOTATION_PROCESSOR = GradleModule(
+            "Configuration Annotation Processor",
+            "ignite-configuration-annotation-processor"
+        )
+        private val IGNITE__CORE = GradleModule(
+            "Ignite Core",
+            "ignite-core"
+        )
+        private val IGNITE__DISTRIBUTION_ZONES = GradleModule(
+            "Distribution Zones",
+            "ignite-distribution-zones"
+        )
+        private val IGNITE__EXAMPLES = GradleModule(
+            "Examples",
+            "ignite-examples"
+        )
+        private val IGNITE__FILE_TRANSFER = GradleModule(
+            "File Transfer",
+            "ignite-file-transfer"
+        )
+        private val IGNITE__FILE_IO = GradleModule(
+            "File IO",
+            "ignite-file-io"
+        )
+        private val IGNITE__INDEX = GradleModule(
+            "Index",
+            "ignite-index"
+        )
+        private val IGNITE__JDBC = GradleModule(
+            "JDBC",
+            "ignite-jdbc"
+        )
+        private val IGNITE__MARSHALLER_COMMON = GradleModule(
+            "Marshaller Common",
+            "ignite-marshaller-common"
+        )
+        private val IGNITE__METASTORAGE = GradleModule(
+            "Metastorage",
+            "ignite-metastorage"
+        )
+        private val IGNITE__METASTORAGE__API = GradleModule(
+            "Metastorage API",
+            "ignite-metastorage-api"
+        )
+        private val IGNITE__METRICS = GradleModule(
+            "Metrics",
+            "ignite-metrics"
+        )
+        private val IGNITE__NETWORK = GradleModule(
+            "Network",
+            "ignite-network"
+        )
+        private val IGNITE__NETWORK_API = GradleModule(
+            "Network API",
+            "ignite-network-api"
+        )
+        private val IGNITE__PAGE_MEMORY = GradleModule(
+            "Page Memory",
+            "ignite-page-memory"
+        )
+        private val IGNITE__PARTITION_REPLICATOR = GradleModule(
+            "Partition Replicator",
+            "ignite-partition-replicator"
+        )
+        private val IGNITE__PLACEMENT_DRIVER = GradleModule(
+            "Placement Driver",
+            "ignite-placement-driver"
+        )
+        private val IGNITE__RAFT = GradleModule(
+            "Raft",
+            "ignite-raft"
+        )
+        private val IGNITE__REST = GradleModule(
+            "Rest",
+            "ignite-rest"
+        )
+        private val IGNITE__REST_API = GradleModule(
+            "Rest API",
+            "ignite-rest-api"
+        )
+        private val IGNITE__REPLICATOR = GradleModule(
+            "Replicator",
+            "ignite-replicator"
+        )
+        private val IGNITE__RUNNER = GradleModule(
+            "Runner",
+            "ignite-runner",
+            "-XX:MaxDirectMemorySize=256m"
+        )
+        private val IGNITE__SECURITY = GradleModule(
+            "Security",
+            "ignite-security"
+        )
+        private val IGNITE__SCHEMA = GradleModule(
+            "Schema",
+            "ignite-schema"
+        )
+        private val IGNITE__SQL_ENGINE = GradleModule(
+            "SQL Engine",
+            "ignite-sql-engine"
+        )
+        private val IGNITE__STORAGE_API = GradleModule(
+            "Storage API",
+            "ignite-storage-api"
+        )
+        private val IGNITE__STORAGE_PAGE_MEMORY = GradleModule(
+            "Storage Page Memory",
+            "ignite-storage-page-memory"
+        )
+        private val IGNITE__STORAGE_ROCKSDB = GradleModule(
+            "Storage RocksDB",
+            "ignite-storage-rocksdb"
+        )
+        private val IGNITE__SYSTEM_DISASTER_RECOVERY = GradleModule(
+            "System Disaster Recovery",
+            "ignite-system-disaster-recovery"
+        )
+        private val IGNITE__TABLE = GradleModule(
+            "Table",
+            "ignite-table"
+        )
+        private val IGNITE__TRANSACTIONS = GradleModule(
+            "Transactions",
+            "ignite-transactions"
+        )
+        private val IGNITE__VAULT = GradleModule(
+            "Vault",
+            "ignite-vault"
+        )
+        private val IGNITE__COMPATIBILITY = GradleModule(
+            "Compatibility",
+            "ignite-compatibility-tests",
+            dependencies = 
listOf(":ignite-compatibility-tests:resolveCompatibilityTestDependencies")
+        )
+        private val MIGRATION_TOOLS_CLI = GradleModule(
+            "Migration Tools - CLI",
+            "migration-tools-cli"
+        )
+        private val MIGRATION_TOOLS_COMMONS = GradleModule(
+            "Migration Tools - Commons",
+            "migration-tools-commons"
+        )
+        private val MIGRATION_TOOLS_CONFIG_CONVERTER = GradleModule(
+            "Migration Tools - Configuration Converter",
+            "migration-tools-config-converter"
+        )
+        private val MIGRATION_TOOLS_PERSISTENCE = GradleModule(
+            "Migration Tools - Persistence",
+            "migration-tools-persistence")
+        private val MIGRATION_TOOLS_E2E_AI3 = GradleModule(
+            "Migration Tools - E2E AI3",
+            "migration-tools-e2e-ai3-tests"
+        )
+        private val MIGRATION_TOOLS_ADAPTER = GradleModule(
+            "Migration Tools - Adapter",
+            "migration-tools-adapter"
+        )
+        private val MIGRATION_TOOLS_ADAPTER_COMPUTE_CORE = GradleModule(
+            "Migration Tools - Compute Core",
+            "migration-tools-adapter-compute-core"
+        )
+        private val MIGRATION_TOOLS_ADAPTER_COMPUTE_BOOTSTRAP = GradleModule(
+            "Migration Tools - Compute Bootstrap",
+            "migration-tools-adapter-compute-bootstrap"
+        )
+        private val MIGRATION_TOOLS_ADAPTER_SPRING_TESTS = GradleModule(
+            "Migration Tools - Spring Data Tests",
+            "migration-tools-adapter-tests-ext-spring-data"
+        )
+        private val MIGRATION_TOOLS_E2E_AI2 = GradleModule(
+            "Migration Tools - E2E AI2",
+            "migration-tools-e2e-adapter-tests"
+        )
+
+        /**
+         * List of GradleModules with Unit tests
+         */
+        private val unitTestGradleModuleList: List<GradleModule> = listOf(
+            IGNITE__API,
+            IGNITE__ARCH_TEST,
+            IGNITE__BINARY_TUPLE,
+            IGNITE__CLI,
+            IGNITE__CLIENT,
+            IGNITE__CLIENT_COMMON,
+            IGNITE__CLIENT_HANDLER,
+            IGNITE__CLUSTER_MANAGEMENT,
+            IGNITE__COMPUTE,
+            IGNITE__CONFIGURATION,
+            IGNITE__CONFIGURATION_ANNOTATION_PROCESSOR,
+            IGNITE__CORE,
+            IGNITE__FILE_IO,
+            IGNITE__INDEX,
+            IGNITE__MARSHALLER_COMMON,
+            IGNITE__METASTORAGE,
+            IGNITE__METASTORAGE__API,
+            IGNITE__METRICS,
+            IGNITE__NETWORK,
+            IGNITE__NETWORK_API,
+            IGNITE__PAGE_MEMORY,
+            IGNITE__PLACEMENT_DRIVER,
+            IGNITE__RAFT,
+            IGNITE__REPLICATOR,
+            IGNITE__REST,
+            IGNITE__REST_API,
+            IGNITE__RUNNER,
+            IGNITE__SCHEMA,
+            IGNITE__SECURITY,
+            IGNITE__SQL_ENGINE,
+            IGNITE__STORAGE_API,
+            IGNITE__STORAGE_PAGE_MEMORY,
+            IGNITE__STORAGE_ROCKSDB,
+            IGNITE__SYSTEM_DISASTER_RECOVERY,
+            IGNITE__TABLE,
+            IGNITE__TRANSACTIONS,
+            IGNITE__VAULT
+        )
+
+        private val integrationTestGradleModulesList: List<GradleModule> = 
listOf(
+            IGNITE__CLI,
+            IGNITE__CLIENT_HANDLER,
+            IGNITE__CLUSTER_MANAGEMENT,
+            IGNITE__CODE_DEPLOYMENT,
+            IGNITE__COMPATIBILITY,
+            IGNITE__COMPUTE,
+            IGNITE__CONFIGURATION_ANNOTATION_PROCESSOR,
+            IGNITE__DISTRIBUTION_ZONES,
+            IGNITE__EXAMPLES,
+            IGNITE__FILE_TRANSFER,
+            IGNITE__INDEX,
+            IGNITE__JDBC,
+            IGNITE__METASTORAGE,
+            IGNITE__METRICS,
+            IGNITE__NETWORK,
+            IGNITE__PAGE_MEMORY,
+            IGNITE__PARTITION_REPLICATOR,
+            IGNITE__PLACEMENT_DRIVER,
+            IGNITE__RAFT,
+            IGNITE__REPLICATOR,
+            IGNITE__REST,
+            IGNITE__RUNNER,
+            IGNITE__SECURITY,
+            IGNITE__SQL_ENGINE,
+            IGNITE__SYSTEM_DISASTER_RECOVERY,
+            IGNITE__TABLE,
+            IGNITE__TRANSACTIONS,
+        )
+
+        private val migrationToolsIntegrationModules: List<GradleModule> = 
listOf(
+            MIGRATION_TOOLS_CONFIG_CONVERTER,
+            MIGRATION_TOOLS_PERSISTENCE,
+            MIGRATION_TOOLS_E2E_AI3,
+        )
+
+        /**
+         * Tests type settings
+         */
+        val UNIT = Tests(TestConfiguration("Unit", "test"), 
unitTestGradleModuleList)
+
+        //JVM_CUSTOM_ARGS to """-XX:MaxDirectMemorySize=256m""".trimIndent()
+        private val integrationTestConf = TestConfiguration(
+            "Integration",
+            "integrationTest",
+            16,
+            60)
+
+        val INTEGRATION = Tests(
+            integrationTestConf,
+            integrationTestGradleModulesList,
+            excludeOnlyModules = migrationToolsIntegrationModules,
+        )
+
+        private val sqlConfigurationLogic = TestConfiguration(
+            "Sql Integration Logic",
+            "integrationTest --tests 
org.apache.ignite.internal.sql.sqllogic.ItSqlLogicTest",
+            4,
+            60,
+            "-DsqlTest")
+        private val sqlConfigurationLogic2 = TestConfiguration(
+            "Sql Integration Logic2",
+            "integrationTest --tests 
org.apache.ignite.internal.sql.sqllogic.ItSqlLogic2Test",
+            4,
+            60,
+            "-DsqlTest")
+        private val sqlConfigurationLogic3 = TestConfiguration(
+            "Sql Integration Logic3",
+            "integrationTest --tests 
org.apache.ignite.internal.sql.sqllogic.ItSqlLogic3Test",
+            4,
+            60,
+            "-DsqlTest")
+
+        val SQL_LOGIC: List<Tests> = listOf(
+            Tests(sqlConfigurationLogic, listOf(IGNITE__SQL_ENGINE),false),
+            Tests(sqlConfigurationLogic2, listOf(IGNITE__SQL_ENGINE),false),
+            Tests(sqlConfigurationLogic3, listOf(IGNITE__SQL_ENGINE),false),
+        )
+
+        val MIGRATION_TOOLS_INTEGRATION: Tests = Tests(
+            TestConfiguration("Integration", "integrationTest", 4, 60, 
dindSupport = true),
+            migrationToolsIntegrationModules,
+            enableOthers = false
+        )
+
+        val MIGRATION_TOOLS_SUITE: RunTests = 
RunTests(MIGRATION_TOOLS_INTEGRATION, "Migration Tools Integration")
+    }
+}
diff --git a/.teamcity/org/apache/ignite/teamcity/CustomBuildSteps.kt 
b/.teamcity/org/apache/ignite/teamcity/CustomBuildSteps.kt
new file mode 100644
index 00000000000..83e7d8656d0
--- /dev/null
+++ b/.teamcity/org/apache/ignite/teamcity/CustomBuildSteps.kt
@@ -0,0 +1,93 @@
+package org.apache.ignite.teamcity
+
+import jetbrains.buildServer.configs.kotlin.BuildSteps
+import jetbrains.buildServer.configs.kotlin.buildSteps.*
+import java.io.File
+
+
+@Suppress("unused")
+class CustomBuildSteps {
+    companion object {
+
+        fun BuildSteps.customGradle(init: GradleBuildStep.() -> Unit): 
GradleBuildStep {
+            val result = GradleBuildStep(init)
+
+            // Use current %JAVA_HOME% as default JDK for compiling using 
Gradle
+            result.jdkHome = if (result.jdkHome == null) "%env.JAVA_HOME%" 
else result.jdkHome
+            result.gradleParams = if (result.gradleParams.isNullOrBlank())
+                "-Dorg.gradle.caching=true" else result.gradleParams.plus(" 
-Dorg.gradle.caching=true")
+            result.useGradleWrapper = true
+            result.workingDir = "%VCSROOT__IGNITE3%"
+
+            step(result)
+            return result
+        }
+
+
+        /**
+         * Custom POWERSHELL build step
+         *
+         * @param filename: name of script file (without path)
+         */
+        fun BuildSteps.customPowerShell(
+            filename: String = "",
+            init: PowerShellStep.() -> Unit
+        ): PowerShellStep {
+            val result = PowerShellStep(init)
+            val file = if (filename == "") 
Teamcity.getBashScriptFileName(result.name) else filename
+
+            result.platform = PowerShellStep.Platform.x64
+            result.edition = PowerShellStep.Edition.Desktop
+            result.noProfile = false
+
+            val scriptModeContent = PowerShellStep.ScriptMode.Script()
+            scriptModeContent.content = 
File("files/scripts/powershell/${file}.ps1").readText()
+            result.scriptMode = scriptModeContent
+
+            step(result)
+            return result
+        }
+
+
+        /**
+         * Custom COMMAND LINE (bash/cmd script) step
+         *
+         * @param type: script type (bash/cmd)
+         * @param filename: name of script file (without path)
+         * @param replacements: ?
+         */
+        fun BuildSteps.customScript(
+            type: String,
+            filename: String = "",
+            replacements: Map<String, String>? = null,
+            init: ScriptBuildStep.() -> Unit
+        ): ScriptBuildStep {
+            val result = ScriptBuildStep(init)
+            // If file name is not specified, use script step name as script 
name accordingly converted
+            val file = if (filename == "") 
Teamcity.getBashScriptFileName(result.name) else filename
+            var extension = ""
+
+            when (type) {
+                "bash" -> {
+                    result.scriptContent = """
+                        #!/usr/bin/env bash
+                        set -o nounset; set -o errexit; set -o pipefail; set 
-o errtrace; set -o functrace
+                        set -x
+                """.trimIndent()
+                    extension = "sh"
+                }
+
+                "cmd" -> {
+                    result.scriptContent = "@ECHO ON"
+                    extension = "cmd"
+                }
+            }
+
+            result.scriptContent += "\n\n\n" + 
File("files/scripts/${type}/${file}.${extension}").readText()
+            replacements?.forEach { (k, v) -> result.scriptContent = 
result.scriptContent?.replace(k, v) }
+
+            step(result)
+            return result
+        }
+    }
+}
\ No newline at end of file
diff --git a/.teamcity/org/apache/ignite/teamcity/CustomBuildType.kt 
b/.teamcity/org/apache/ignite/teamcity/CustomBuildType.kt
new file mode 100644
index 00000000000..36447bf0268
--- /dev/null
+++ b/.teamcity/org/apache/ignite/teamcity/CustomBuildType.kt
@@ -0,0 +1,104 @@
+package org.apache.ignite.teamcity
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import jetbrains.buildServer.configs.kotlin.BuildTypeSettings.Type
+import jetbrains.buildServer.configs.kotlin.CheckoutMode
+import 
org.apache.ignite.teamcity.CustomFailureConditions.Companion.failOnExactText
+
+@Suppress("unused")
+open class CustomBuildType(open val buildType: BuildType) {
+    open class Builder(open var buildType: BuildType) {
+        /**
+         * Default settings for every Apache Ignite 3 TeamCity build 
configuration
+         */
+        @Suppress("unused")
+        fun defaultBuildTypeSettings() = apply {
+            buildType.vcs {
+                checkoutMode = if (checkoutMode == CheckoutMode.AUTO) 
CheckoutMode.ON_SERVER else checkoutMode
+                cleanCheckout = true
+                showDependenciesChanges = true
+            }
+
+            buildType.failureConditions {
+                executionTimeoutMin = if (buildType.type == Type.COMPOSITE) 0
+                else if (executionTimeoutMin == 0) 30 else executionTimeoutMin
+            }
+        }
+
+
+        /**
+         * Linux-based agent requirement
+         */
+        @Suppress("unused")
+        fun requireLinux() = apply {
+            buildType.requirements {
+                equals("teamcity.agent.jvm.os.name", "Linux")
+            }
+        }
+
+
+        /**
+         * Non docker-in-docker-based agent requirement
+         */
+        @Suppress("unused")
+        fun requireNonDind() = apply {
+            buildType.requirements {
+                doesNotExist("env.DIND_ENABLED")
+            }
+        }
+
+
+        /**
+         * Docker-in-docker-based agent requirement
+         */
+        @Suppress("unused")
+        fun requireDind() = apply {
+            buildType.requirements {
+                equals("env.DIND_ENABLED", "true")
+            }
+        }
+
+
+        /**
+         * Windows-based agent requirement
+         */
+        @Suppress("unused")
+        fun requireWindows() = apply {
+            buildType.requirements {
+                startsWith("teamcity.agent.jvm.os.name", "Windows")
+            }
+        }
+
+
+        /**
+         * Clean all build run information in 24h
+         */
+        @Suppress("unused")
+        fun immediateCleanup() = apply {
+            buildType.cleanup {
+                baseRule {
+                    all(days = 1)
+                }
+            }
+        }
+
+
+        /**
+         * Apply additional failure conditions for tests based on messages in 
the build log
+         */
+        fun testsFailureCondition() = apply {
+            buildType.failureConditions {
+                failOnExactText(pattern = "LEAK:", failureMessage = "Netty 
buffer leak detected.") {}
+                failOnExactText(pattern = "java.lang.NullPointerException", 
failureMessage = "NullPointerException detected.") {}
+                failOnExactText(pattern = "java.lang.AssertionError", 
failureMessage = "AssertionError detected.") {}
+                failOnExactText(pattern = "Critical system error detected.", 
failureMessage = "Critical system error detected.") {}
+            }
+        }
+
+
+        /**
+         * Return updated BuildType object
+         */
+        fun build() = CustomBuildType(buildType)
+    }
+}
\ No newline at end of file
diff --git a/.teamcity/org/apache/ignite/teamcity/CustomFailureConditions.kt 
b/.teamcity/org/apache/ignite/teamcity/CustomFailureConditions.kt
new file mode 100644
index 00000000000..535f354e0e2
--- /dev/null
+++ b/.teamcity/org/apache/ignite/teamcity/CustomFailureConditions.kt
@@ -0,0 +1,27 @@
+package org.apache.ignite.teamcity
+
+import jetbrains.buildServer.configs.kotlin.FailureConditions
+import 
jetbrains.buildServer.configs.kotlin.failureConditions.BuildFailureOnText
+
+
+@Suppress("unused")
+class CustomFailureConditions {
+    companion object {
+        fun FailureConditions.failOnExactText(
+            pattern: String,
+            failureMessage: String,
+            init: BuildFailureOnText.() -> Unit
+        ): BuildFailureOnText {
+            val result = BuildFailureOnText(init)
+
+            result.conditionType = BuildFailureOnText.ConditionType.CONTAINS
+            result.pattern = pattern
+            result.failureMessage = failureMessage
+            result.reverse = false
+            result.reportOnlyFirstMatch = false
+
+            failureCondition(result)
+            return result
+        }
+    }
+}
\ No newline at end of file
diff --git a/.teamcity/org/apache/ignite/teamcity/CustomTriggers.kt 
b/.teamcity/org/apache/ignite/teamcity/CustomTriggers.kt
new file mode 100644
index 00000000000..a20af3a42b2
--- /dev/null
+++ b/.teamcity/org/apache/ignite/teamcity/CustomTriggers.kt
@@ -0,0 +1,99 @@
+package org.apache.ignite.teamcity
+
+import jetbrains.buildServer.configs.kotlin.Triggers
+import jetbrains.buildServer.configs.kotlin.triggers.ScheduleTrigger
+import jetbrains.buildServer.configs.kotlin.triggers.VcsTrigger
+
+@Suppress("unused")
+class CustomTriggers {
+    companion object {
+        /**
+         * Custom SCHEDULE trigger
+         *
+         * @param triggerHour: hour
+         * @param branchFilter: filter out target branch to trigger
+         * @param enabled: enable/disable trigger
+         */
+        fun Triggers.customSchedule(
+            triggerHour: Int,
+            branchFilter: String,
+            enabled: Boolean = true,
+            init: ScheduleTrigger.() -> Unit
+        ): ScheduleTrigger {
+            val result = ScheduleTrigger(init)
+
+            // Set hour in schedule (minutes default to 00)
+            result.schedulingPolicy = result.daily {
+                hour = triggerHour
+            }
+            // Allow to enable/disable trigger
+            result.enabled = enabled
+            // Filter branches (run on only specified ones)
+            result.branchFilter = branchFilter
+            // Run build despite the watching build is not changed
+            result.triggerBuild = result.always()
+            // Run build despite there are no pending changes in the build
+            result.withPendingChangesOnly = false
+            // Run build without build optimisation (stop if newer build is 
already running or finished)
+            result.enableQueueOptimization = false
+            // Force clean checkout (rebuild dependant builds)
+            result.enforceCleanCheckoutForDependencies = true
+
+            trigger(result)
+            return result
+        }
+
+
+        /**
+         * Trigger for changes in GitHub pull-request
+         *
+         * @param enabled: enable/disable trigger
+         * @param quietPeriod: set custom quiet period time (seconds)
+         */
+        fun Triggers.pullRequestChange(
+            enabled: Boolean = true,
+            quietPeriod: Int = 300,
+            init: VcsTrigger.() -> Unit
+        ): VcsTrigger {
+            val result = VcsTrigger(init)
+
+            // Filter pull-requests
+            result.branchFilter = "+:pull/*"
+            // Allow to enable/disable trigger
+            result.enabled = enabled
+            result.enableQueueOptimization = true
+            result.quietPeriodMode = VcsTrigger.QuietPeriodMode.USE_CUSTOM
+            result.quietPeriod = quietPeriod
+
+            trigger(result)
+            return result
+        }
+
+        /**
+         * Trigger for changes in Integration Branch
+         *
+         * @param enabled: enable/disable trigger
+         * @param integrationBranchName: set custom branch name
+         * @param quietPeriod: set custom quiet period time (seconds)
+         */
+        fun Triggers.integrationBranchChange(
+            enabled: Boolean = true,
+            integrationBranchName: String = "main",
+            quietPeriod: Int = 300,
+            init: VcsTrigger.() -> Unit
+        ): VcsTrigger {
+            val result = VcsTrigger(init)
+
+            // Trigger only on integration branch
+            result.branchFilter = "+:${integrationBranchName}"
+            // Allow to enable/disable trigger
+            result.enabled = enabled
+            result.enableQueueOptimization = true
+            result.quietPeriodMode = VcsTrigger.QuietPeriodMode.USE_CUSTOM
+            result.quietPeriod = quietPeriod
+
+            trigger(result)
+            return result
+        }
+    }
+}
\ No newline at end of file
diff --git a/.teamcity/org/apache/ignite/teamcity/Teamcity.kt 
b/.teamcity/org/apache/ignite/teamcity/Teamcity.kt
new file mode 100644
index 00000000000..7d10fba34bb
--- /dev/null
+++ b/.teamcity/org/apache/ignite/teamcity/Teamcity.kt
@@ -0,0 +1,121 @@
+package org.apache.ignite.teamcity
+
+import jetbrains.buildServer.configs.kotlin.ParameterDisplay
+import jetbrains.buildServer.configs.kotlin.ParametrizedWithType
+import kotlin.reflect.KClass
+
+
+class Teamcity {
+    companion object {
+        /*************
+         * FUNCTIONS *
+         *************/
+        /**
+         * Convert step name to script file name
+         */
+        fun getBashScriptFileName(name: String): String {
+            // Translate step name to script name
+            val array = name.replace("""[()+.:-]""".toRegex(), " ").split(" 
").toTypedArray()
+            for (i in array.indices) { array[i] = array[i].replaceFirstChar { 
it.uppercase() } }
+
+            return array.joinToString(separator = "").replace("/", "_")
+        }
+
+
+        /**
+         * Convert Project or BuildType fully-qualified class name into ID
+         */
+        @Suppress("unused", "unused")
+        fun getId(kClass: KClass<*>, customClassName: String? = null, 
isParametrizedClass: Boolean = false): String {
+            // Disassemble qualified class name into packages and class name
+            val list = 
kClass.qualifiedName.toString().split(".").toMutableList()
+
+            // Remove Project parts of qualified class name which do not 
participate in id naming
+            arrayOf(
+                "Project",
+                "build_types", "_build_types",
+                "template_types", "_template_types"
+            ).forEach { list.remove(it) }
+            if (isParametrizedClass) list.removeLast()
+
+            // Process every element of list
+            for (i in list.indices) {
+                // Convert class names with underscore
+                val sublist = list[i].split("_").toMutableList()
+                for (j in sublist.indices) { sublist[j] = 
sublist[j].replaceFirstChar { it.uppercase() } }
+                list[i] = sublist.joinToString("")
+
+                // Capitalized every element of list
+                list[i] = list[i].replaceFirstChar { it.uppercase() }
+            }
+
+            // Replace class name with custom
+            if (customClassName != null) {
+                list.add(customClassName.replace("""[ 
&=+./>:()-]""".toRegex(), ""))
+//                list[list.lastIndex] = customClassName.replace("""[ 
&=+./>:()-]""".toRegex(), "")
+            }
+
+            return list.joinToString(separator = "_")
+        }
+
+
+        /*****************
+         * CUSTOM PARAMS *
+         *****************/
+        /**
+         * Hidden text field
+         */
+        @Suppress("MemberVisibilityCanBePrivate")
+        fun ParametrizedWithType.hiddenText(name: String, value: String) {
+            text(name, value, display = ParameterDisplay.HIDDEN, allowEmpty = 
true)
+        }
+
+
+        /**
+         * Hidden password field
+         */
+        @Suppress("unused")
+        fun ParametrizedWithType.hiddenPassword(name: String, value: String) {
+            password(name, value, display = ParameterDisplay.HIDDEN)
+        }
+
+        /**
+        * Custom constructable text param for PATH environment variable
+         * Provides ability to add param with several additional paths added 
to env.PATH depending on required binary
+         *
+         * @param binList list of possible binaries to add to PATH. Valid 
values:
+         *  - maven
+         */
+        @Suppress("unused")
+        fun ParametrizedWithType.customPATH(binList: List<String>) {
+            val pathList: MutableList<String> = mutableListOf()
+
+            // Add matching paths to list of paths
+            binList.forEach {
+                when (it) { "maven" -> 
pathList.add("%teamcity.tool.maven.DEFAULT%/bin") }
+            }
+
+            // Add all other paths (to avoid PATH override)
+            pathList.add("%env.PATH%")
+
+            hiddenText("env.PATH", pathList.joinToString(separator = ":"))
+        }
+
+
+        /**
+         * Adds reverse dependency param assignment for usage inside build 
configuration
+         *
+         * @param buildTypeClass 'BuildType' class instance
+         * @param paramName name of parameter to add reverse dependency to
+         *
+         * @return param name with reverse dependency prefix
+         */
+        @Suppress("unused")
+        fun addReverseParam(buildTypeClass: CustomBuildType.Builder, 
paramName: String, direct: Boolean): String {
+            val reverseParamName = "rev.dep.*.$paramName"
+            if (direct) buildTypeClass.apply { buildType.params { 
hiddenText(paramName, reverseParamName) } }
+
+            return reverseParamName
+        }
+    }
+}
diff --git a/.teamcity/pom.xml b/.teamcity/pom.xml
new file mode 100644
index 00000000000..529b4b8aab3
--- /dev/null
+++ b/.teamcity/pom.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0"?>
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <name>ApacheIgnite3 Config DSL Script</name>
+  <groupId>ApacheIgnite3</groupId>
+  <artifactId>ApacheIgnite3_dsl</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <parent>
+    <groupId>org.jetbrains.teamcity</groupId>
+    <artifactId>configs-dsl-kotlin-parent</artifactId>
+    <version>1.0-SNAPSHOT</version>
+  </parent>
+
+  <repositories>
+    <repository>
+      <id>jetbrains-all</id>
+      <url>https://download.jetbrains.com/teamcity-repository</url>
+      <snapshots>
+        <enabled>true</enabled>
+      </snapshots>
+    </repository>
+    <repository>
+      <id>teamcity-server</id>
+      <url>http://ci.ignite.apache.org/app/dsl-plugins-repository</url>
+      <snapshots>
+        <enabled>true</enabled>
+      </snapshots>
+    </repository>
+  </repositories>
+
+  <pluginRepositories>
+    <pluginRepository>
+      <id>JetBrains</id>
+      <url>https://download.jetbrains.com/teamcity-repository</url>
+    </pluginRepository>
+  </pluginRepositories>
+
+  <build>
+    <sourceDirectory>${basedir}</sourceDirectory>
+    <plugins>
+      <plugin>
+        <artifactId>kotlin-maven-plugin</artifactId>
+        <groupId>org.jetbrains.kotlin</groupId>
+        <version>${kotlin.version}</version>
+
+        <configuration/>
+        <executions>
+          <execution>
+            <id>compile</id>
+            <phase>process-sources</phase>
+            <goals>
+              <goal>compile</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>test-compile</id>
+            <phase>process-test-sources</phase>
+            <goals>
+              <goal>test-compile</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.jetbrains.teamcity</groupId>
+        <artifactId>teamcity-configs-maven-plugin</artifactId>
+        <version>${teamcity.dsl.version}</version>
+        <configuration>
+          <format>kotlin</format>
+          <dstDir>target/generated-configs</dstDir>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.jetbrains.teamcity</groupId>
+      <artifactId>configs-dsl-kotlin-latest</artifactId>
+      <version>${teamcity.dsl.version}</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jetbrains.teamcity</groupId>
+      <artifactId>configs-dsl-kotlin-plugins-latest</artifactId>
+      <version>1.0-SNAPSHOT</version>
+      <type>pom</type>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jetbrains.kotlin</groupId>
+      <artifactId>kotlin-stdlib-jdk8</artifactId>
+      <version>${kotlin.version}</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jetbrains.kotlin</groupId>
+      <artifactId>kotlin-script-runtime</artifactId>
+      <version>${kotlin.version}</version>
+      <scope>compile</scope>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file
diff --git a/.teamcity/settings.kts b/.teamcity/settings.kts
new file mode 100644
index 00000000000..46fd6530f3a
--- /dev/null
+++ b/.teamcity/settings.kts
@@ -0,0 +1,27 @@
+import jetbrains.buildServer.configs.kotlin.version
+import jetbrains.buildServer.configs.kotlin.project
+
+/*
+The settings script is an entry point for defining a TeamCity
+project hierarchy. The script should contain a single call to the
+project() function with a Project instance or an init function as
+an argument.
+
+VcsRoots, BuildTypes, Templates, and subprojects can be
+registered inside the project using the vcsRoot(), buildType(),
+template(), and subProject() methods respectively.
+
+To debug settings scripts in command-line, run the
+
+    mvnDebug org.jetbrains.teamcity:teamcity-configs-maven-plugin:generate
+
+command and attach your debugger to the port 8000.
+
+To debug in IntelliJ Idea, open the 'Maven Projects' tool window (View
+-> Tool Windows -> Maven Projects), find the generate task node
+(Plugins -> teamcity-configs -> teamcity-configs:generate), the
+'Debug' option is available in the context menu for the task.
+*/
+
+version = "2025.07"
+project(_Self.Project)
diff --git a/.teamcity/test/Project.kt b/.teamcity/test/Project.kt
new file mode 100644
index 00000000000..6a49c380520
--- /dev/null
+++ b/.teamcity/test/Project.kt
@@ -0,0 +1,77 @@
+package test
+
+import jetbrains.buildServer.configs.kotlin.Project
+import org.apache.ignite.teamcity.ApacheIgnite3CustomBuildType
+import org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.INTEGRATION
+import 
org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.MIGRATION_TOOLS_SUITE
+import org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.SQL_LOGIC
+import org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.UNIT
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+import test.build_types.RunAllTests
+import test.build_types.RunAllTestsCustomJDK
+import test.build_types.RunPlatformTests
+import test.build_types.RunSanityCheck
+import test.platform_tests.PlatformDotnetTestsLinux
+import test.template_types.RunTests
+import test.template_types.RunTestsList
+
+
+object Project : Project({
+    id(getId(this::class))
+    name = "[Test]"
+
+    subProject(test.integration_tests.Project)
+    subProject(test.sanity_check.Project)
+    subProject(test.unit_tests.Project)
+    subProject(test.platform_tests.Project)
+
+    buildType(
+        ApacheIgnite3CustomBuildType.Builder(RunAllTests)
+            .ignite3VCS().ignite3CommitStatusPublisher()
+            .defaultBuildTypeSettings().requireLinux()
+            .build().buildType
+    )
+    buildType(
+        ApacheIgnite3CustomBuildType.Builder(RunAllTestsCustomJDK)
+            .ignite3VCS()
+            .defaultBuildTypeSettings().requireLinux()
+            .build().buildType
+    )
+    buildType(
+        ApacheIgnite3CustomBuildType.Builder(RunSanityCheck)
+            .ignite3VCS().ignite3CommitStatusPublisher()
+            .defaultBuildTypeSettings().requireLinux()
+            .build().buildType
+    )
+    buildType(
+        ApacheIgnite3CustomBuildType.Builder(RunPlatformTests)
+            .ignite3VCS().ignite3CommitStatusPublisher()
+            .defaultBuildTypeSettings().requireLinux()
+            .build().buildType
+    )
+    buildType(
+        ApacheIgnite3CustomBuildType.Builder(RunTests(INTEGRATION))
+            .ignite3VCS().ignite3CommitStatusPublisher()
+            .defaultBuildTypeSettings().requireLinux()
+            .build().buildType
+    )
+    buildType(
+        ApacheIgnite3CustomBuildType.Builder(MIGRATION_TOOLS_SUITE)
+            .ignite3VCS()
+            .defaultBuildTypeSettings().requireLinux()
+            .build().buildType
+    )
+    buildType(
+        ApacheIgnite3CustomBuildType.Builder(RunTests(UNIT))
+            .ignite3VCS().ignite3CommitStatusPublisher()
+            .defaultBuildTypeSettings().requireLinux()
+            .build().buildType
+    )
+    buildType(
+        ApacheIgnite3CustomBuildType.Builder(RunTestsList(SQL_LOGIC, 
SQL_LOGIC[0].configuration.suiteId))
+            .ignite3VCS()
+            .defaultBuildTypeSettings().requireLinux()
+            .build().buildType
+    )
+})
+
diff --git a/.teamcity/test/build_types/RunAllTests.kt 
b/.teamcity/test/build_types/RunAllTests.kt
new file mode 100644
index 00000000000..a42e02a0b6a
--- /dev/null
+++ b/.teamcity/test/build_types/RunAllTests.kt
@@ -0,0 +1,47 @@
+package test.build_types
+
+import _Self.isActiveProject
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomTriggers.Companion.customSchedule
+import org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.INTEGRATION
+import 
org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.MIGRATION_TOOLS_SUITE
+import org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.SQL_LOGIC
+import org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.UNIT
+import 
org.apache.ignite.teamcity.CustomTriggers.Companion.integrationBranchChange
+import org.apache.ignite.teamcity.CustomTriggers.Companion.pullRequestChange
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+import org.apache.ignite.teamcity.Teamcity.Companion.hiddenText
+import test.template_types.RunTests
+import test.template_types.RunTestsList
+
+object RunAllTests : BuildType({
+    id(getId(this::class))
+    name = "--> Run :: All Tests"
+    description = "Run all tests at once"
+    type = Type.COMPOSITE
+
+    triggers {
+        customSchedule(5, "+:<default>", enabled = isActiveProject) {
+            buildParams {
+                checkbox("IGNITE_COMPATIBILITY_TEST_ALL_VERSIONS", "true")
+            }
+        }
+        pullRequestChange(enabled = isActiveProject) {}
+        integrationBranchChange(enabled = isActiveProject) {}
+    }
+
+    params {
+        checkbox("reverse.dep.*.IGNITE_COMPATIBILITY_TEST_ALL_VERSIONS", 
"-DtestAllVersions=false", label = "Test All Versions", description = "Test all 
versions in compatibility tests", checked = "-DtestAllVersions=true", unchecked 
= "-DtestAllVersions=false")
+        checkbox("reverse.dep.*.IGNITE_ZONE_BASED_REPLICATION", 
"-DIGNITE_ZONE_BASED_REPLICATION=true", label = "Enable Zone-based 
replication", checked = "-DIGNITE_ZONE_BASED_REPLICATION=true", unchecked = 
"-DIGNITE_ZONE_BASED_REPLICATION=false")
+        select("reverse.dep.*.IGNITE_DEFAULT_STORAGE_ENGINE", "", label = 
"Default Storage Engine", options = listOf("Default" to "", "aimem" to 
"-DIGNITE_DEFAULT_STORAGE_ENGINE=aimem", "rocksdb" to 
"-DIGNITE_DEFAULT_STORAGE_ENGINE=rocksdb"))
+    }
+
+    dependencies {
+        snapshot(RunSanityCheck) {}
+        snapshot(RunPlatformTests) {}
+        snapshot(RunTests(INTEGRATION)) {}
+        snapshot(MIGRATION_TOOLS_SUITE) {}
+        snapshot(RunTests(UNIT)) {}
+        snapshot(RunTestsList(SQL_LOGIC, SQL_LOGIC[0].configuration.suiteId)) 
{}
+    }
+})
diff --git a/.teamcity/test/build_types/RunAllTestsCustomJDK.kt 
b/.teamcity/test/build_types/RunAllTestsCustomJDK.kt
new file mode 100644
index 00000000000..8c0b9770ded
--- /dev/null
+++ b/.teamcity/test/build_types/RunAllTestsCustomJDK.kt
@@ -0,0 +1,33 @@
+package test.build_types
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.INTEGRATION
+import 
org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.MIGRATION_TOOLS_SUITE
+import org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.SQL_LOGIC
+import org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.UNIT
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+import org.apache.ignite.teamcity.Teamcity.Companion.hiddenText
+import test.template_types.RunTests
+import test.template_types.RunTestsList
+
+object RunAllTestsCustomJDK : BuildType({
+    id(getId(this::class))
+    name = "--> Run :: All Tests [JDK 11/21]"
+    description = "Run all tests on custom JDK at once"
+    type = Type.COMPOSITE
+
+    params {
+        checkbox("reverse.dep.*.IGNITE_COMPATIBILITY_TEST_ALL_VERSIONS", 
"-DtestAllVersions=false", label = "Test All Versions", description = "Test all 
versions in compatibility tests", checked = "-DtestAllVersions=true", unchecked 
= "-DtestAllVersions=false")
+        checkbox("reverse.dep.*.IGNITE_ZONE_BASED_REPLICATION", 
"-DIGNITE_ZONE_BASED_REPLICATION=false", label = "Disable Zone-based 
replication", checked = "-DIGNITE_ZONE_BASED_REPLICATION=true", unchecked = 
"-DIGNITE_ZONE_BASED_REPLICATION=false")
+        select("reverse.dep.*.IGNITE_DEFAULT_STORAGE_ENGINE", "", label = 
"Default Storage Engine", options = listOf("Default" to "", "aimem" to 
"-DIGNITE_DEFAULT_STORAGE_ENGINE=aimem", "rocksdb" to 
"-DIGNITE_DEFAULT_STORAGE_ENGINE=rocksdb"))
+    }
+
+    dependencies {
+        snapshot(RunSanityCheck) {}
+        snapshot(RunPlatformTests) {}
+        snapshot(RunTests(INTEGRATION)) {}
+        snapshot(MIGRATION_TOOLS_SUITE) {}
+        snapshot(RunTests(UNIT)) {}
+        snapshot(RunTestsList(SQL_LOGIC, SQL_LOGIC[0].configuration.suiteId)) 
{}
+    }
+})
diff --git a/.teamcity/test/build_types/RunPlatformTests.kt 
b/.teamcity/test/build_types/RunPlatformTests.kt
new file mode 100644
index 00000000000..273c30a9fe3
--- /dev/null
+++ b/.teamcity/test/build_types/RunPlatformTests.kt
@@ -0,0 +1,20 @@
+package test.build_types
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+import test.platform_tests.*
+
+object RunPlatformTests : BuildType({
+    id(getId(this::class))
+    name = "> Run :: Platform Tests"
+    description = "Run all platform tests at once"
+    type = Type.COMPOSITE
+
+    dependencies {
+        snapshot(PlatformCppTestsLinux) {}
+//        snapshot(PlatformCppTestsWindows) {}  // Always falling, under 
investigation
+        snapshot(PlatformDotnetTestsWindows) {}
+        snapshot(PlatformDotnetTestsLinux) {}
+        snapshot(PlatformPythonTestsLinux) {}
+    }
+})
diff --git a/.teamcity/test/build_types/RunSanityCheck.kt 
b/.teamcity/test/build_types/RunSanityCheck.kt
new file mode 100644
index 00000000000..b7575cfbf46
--- /dev/null
+++ b/.teamcity/test/build_types/RunSanityCheck.kt
@@ -0,0 +1,22 @@
+package test.build_types
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+import test.sanity_check.build_types.*
+
+
+object RunSanityCheck : BuildType({
+    id(getId(this::class))
+    name = "-> Run :: Sanity Check"
+    description = "Run all sanity checks at once"
+    type = Type.COMPOSITE
+
+    dependencies {
+        snapshot(AssembleTestClasses) {}
+        snapshot(CodeStyle) {}
+        snapshot(Javadoc) {}
+        snapshot(MentionTicket) {}
+        snapshot(PMD) {}
+        snapshot(Spotbugs) {}
+    }
+})
diff --git a/.teamcity/test/integration_tests/Project.kt 
b/.teamcity/test/integration_tests/Project.kt
new file mode 100644
index 00000000000..9a0fe46f421
--- /dev/null
+++ b/.teamcity/test/integration_tests/Project.kt
@@ -0,0 +1,16 @@
+package test.integration_tests
+
+import jetbrains.buildServer.configs.kotlin.Project
+import org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.INTEGRATION
+import 
org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.MIGRATION_TOOLS_INTEGRATION
+import org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.SQL_LOGIC
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+
+object Project : Project({
+    id(getId(this::class))
+    name = "[Integration Tests]"
+
+    INTEGRATION.buildType().forEach { buildType(it) }
+    MIGRATION_TOOLS_INTEGRATION.buildType().forEach { buildType(it) }
+    SQL_LOGIC.forEach { tests -> tests.buildType().forEach { buildType(it) } }
+})
diff --git a/.teamcity/test/platform_tests/PlatformCppTestsLinux.kt 
b/.teamcity/test/platform_tests/PlatformCppTestsLinux.kt
new file mode 100644
index 00000000000..03739872b2f
--- /dev/null
+++ b/.teamcity/test/platform_tests/PlatformCppTestsLinux.kt
@@ -0,0 +1,153 @@
+package test.platform_tests
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import jetbrains.buildServer.configs.kotlin.ParameterDisplay
+import jetbrains.buildServer.configs.kotlin.buildFeatures.XmlReport
+import jetbrains.buildServer.configs.kotlin.buildFeatures.xmlReport
+import jetbrains.buildServer.configs.kotlin.buildSteps.*
+import 
jetbrains.buildServer.configs.kotlin.failureConditions.BuildFailureOnText
+import jetbrains.buildServer.configs.kotlin.failureConditions.failOnText
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customScript
+import org.apache.ignite.teamcity.Teamcity
+
+
+object PlatformCppTestsLinux : BuildType({
+    id(Teamcity.getId(this::class))
+    name = "Platform C++ Tests (Linux)"
+
+    artifactRules = """
+        %PATH__UNIT_TESTS_RESULT% => test_logs
+        %PATH__CLIENT_TEST_RESULTS% => test_logs
+        %PATH__CMAKE_BUILD_DIRECTORY%/core => core_dumps
+    """.trimIndent()
+
+    params {
+        param("env.IGNITE_CPP_TESTS_USE_SINGLE_NODE", "")
+        param("PATH__CMAKE_BUILD_DIRECTORY", 
"%PATH__WORKING_DIR%/cmake-build-debug")
+        param("PATH__CLIENT_TEST_RESULTS", 
"%PATH__WORKING_DIR%/cpp_client_tests_results.xml")
+        param("PATH__ODBC_TEST_RESULTS", 
"%PATH__WORKING_DIR%/odbc_tests_results.xml")
+        param("PATH__UNIT_TESTS_RESULT", 
"%PATH__WORKING_DIR%/cpp_unit_test_results.xml")
+        text("PATH__WORKING_DIR", "%VCSROOT__IGNITE3%/modules/platforms/cpp", 
display = ParameterDisplay.HIDDEN, allowEmpty = true)
+        param("env.CPP_STAGING", "/tmp/cpp_staging")
+    }
+
+    steps {
+        script {
+            name = "Build Info"
+            workingDir = "%PATH__WORKING_DIR%"
+            scriptContent = """
+                gcc --version || exit 0
+                g++ --version || exit 0
+                
+                odbcinst -j || exit 0
+                cat /etc/odbcinst.ini || exit 0
+            """.trimIndent()
+        }
+        script {
+            name = "Build C++"
+            scriptContent = """
+                mkdir %PATH__CMAKE_BUILD_DIRECTORY%  || exit 2
+                cd %PATH__CMAKE_BUILD_DIRECTORY%  || exit 3
+                
+                cmake .. -DENABLE_TESTS=ON -DENABLE_ODBC=ON 
-DWARNINGS_AS_ERRORS=ON -DCMAKE_BUILD_TYPE=Debug 
-DCMAKE_INSTALL_PREFIX=%env.CPP_STAGING% || (echo 'CMake configuration failed' 
&& exit 5)
+                cmake --build . -j8  || (echo 'CMake build failed' && exit 6)
+                cmake --install . || (echo 'CMake install failed' && exit 7)
+            """.trimIndent()
+        }
+        customScript(type = "bash") {
+            name = "Clean Up Remaining Processes"
+        }
+        customGradle {
+            name = "Verify runner is builded"
+            tasks = ":ignite-runner:integrationTestClasses"
+        }
+        customScript(type = "bash") {
+            name = "Clean Up Remaining Processes"
+        }
+        script {
+            name = "Unit tests"
+            workingDir = "%PATH__CMAKE_BUILD_DIRECTORY%"
+            scriptContent = """
+                ctest --version
+                ctest -E '(IgniteClientTest|IgniteOdbcTest)' --output-junit 
%PATH__UNIT_TESTS_RESULT%  || exit 0
+            """.trimIndent()
+            formatStderrAsError = true
+        }
+        script {
+            name = "C++ Client integration tests"
+            workingDir = "%PATH__CMAKE_BUILD_DIRECTORY%"
+            scriptContent = "./bin/ignite-client-test 
--gtest_output=xml:%PATH__CLIENT_TEST_RESULTS%"
+            formatStderrAsError = true
+        }
+        customScript(type = "bash") {
+            name = "Clean Up Remaining Processes"
+        }
+        script {
+            name = "ODBC integration tests"
+            workingDir = "%PATH__CMAKE_BUILD_DIRECTORY%"
+            scriptContent = """
+                if [ -f "./bin/ignite-odbc-test" ]; then
+                  ./bin/ignite-odbc-test 
--gtest_output=xml:%PATH__ODBC_TEST_RESULTS%
+                fi
+            """.trimIndent()
+            formatStderrAsError = true
+        }
+        customScript(type = "bash") {
+            name = "Clean Up Remaining Processes"
+        }
+    }
+
+    failureConditions {
+        executionTimeoutMin = 15
+        failOnText {
+            conditionType = BuildFailureOnText.ConditionType.CONTAINS
+            pattern = "CMake configuration failed"
+            failureMessage = "CMake configuration failed"
+            reverse = false
+        }
+        failOnText {
+            conditionType = BuildFailureOnText.ConditionType.CONTAINS
+            pattern = "CMake build failed"
+            failureMessage = "CMake build failed"
+            reverse = false
+        }
+        failOnText {
+            conditionType = BuildFailureOnText.ConditionType.CONTAINS
+            pattern = "CMake install failed"
+            failureMessage = "CMake install failed"
+            reverse = false
+        }
+        failOnText {
+            conditionType = BuildFailureOnText.ConditionType.CONTAINS
+            pattern = "FAILED TEST SUITE"
+            failureMessage = "One or several test suites have failed during 
SetUpTestSuite"
+            reverse = false
+        }
+    }
+
+    features {
+        xmlReport {
+            reportType = XmlReport.XmlReportType.GOOGLE_TEST
+            rules = """
+                +:%PATH__CLIENT_TEST_RESULTS%
+                +:%PATH__ODBC_TEST_RESULTS%
+                +:%PATH__CMAKE_BUILD_DIRECTORY%/Testing/Result/*.xml
+            """.trimIndent()
+            verbose = true
+        }
+        xmlReport {
+            reportType = XmlReport.XmlReportType.CTEST
+            rules = "+:%PATH__UNIT_TESTS_RESULT%"
+            verbose = true
+        }
+    }
+
+    /**
+     *  Temporary lock Platform Linux jobs on old-type agents
+     *  until execution of these tests is fixed on DIND agents
+     */
+    requirements {
+        doesNotExist("env.DIND_ENABLED")
+    }
+})
diff --git a/.teamcity/test/platform_tests/PlatformCppTestsWindows.kt 
b/.teamcity/test/platform_tests/PlatformCppTestsWindows.kt
new file mode 100644
index 00000000000..9a538e942a5
--- /dev/null
+++ b/.teamcity/test/platform_tests/PlatformCppTestsWindows.kt
@@ -0,0 +1,151 @@
+package test.platform_tests
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import jetbrains.buildServer.configs.kotlin.ParameterDisplay
+import jetbrains.buildServer.configs.kotlin.buildFeatures.XmlReport
+import jetbrains.buildServer.configs.kotlin.buildFeatures.xmlReport
+import jetbrains.buildServer.configs.kotlin.buildSteps.*
+import 
jetbrains.buildServer.configs.kotlin.failureConditions.BuildFailureOnMetric
+import 
jetbrains.buildServer.configs.kotlin.failureConditions.BuildFailureOnText
+import 
jetbrains.buildServer.configs.kotlin.failureConditions.failOnMetricChange
+import jetbrains.buildServer.configs.kotlin.failureConditions.failOnText
+import jetbrains.buildServer.configs.kotlin.triggers.vcs
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customScript
+import org.apache.ignite.teamcity.Teamcity
+import org.apache.ignite.teamcity.Teamcity.Companion.hiddenText
+
+
+object PlatformCppTestsWindows : BuildType({
+    id(Teamcity.getId(this::class))
+    name = "Platform C++ Tests (Windows)"
+
+    artifactRules = """
+        %PATH__UNIT_TESTS_RESULT% => test_logs
+        %PATH__CLIENT_TEST_RESULTS% => test_logs
+    """.trimIndent()
+
+    params {
+        hiddenText("env.IGNITE_CPP_TESTS_USE_SINGLE_NODE", "")
+        hiddenText("PATH__CMAKE_BUILD_DIRECTORY", 
"""%PATH__WORKING_DIR%\cmake-build-debug""")
+        hiddenText("PATH__CLIENT_TEST_RESULTS", 
"""%PATH__CMAKE_BUILD_DIRECTORY%\cpp_client_tests_results.xml""")
+        hiddenText("PATH__ODBC_TEST_RESULTS", 
"""%PATH__CMAKE_BUILD_DIRECTORY%\odbc_tests_results.xml""")
+        hiddenText("PATH__UNIT_TESTS_RESULT", 
"""%PATH__CMAKE_BUILD_DIRECTORY%\cpp_unit_test_results.xml""")
+        hiddenText("PATH__WORKING_DIR", 
"""%VCSROOT__IGNITE3%\modules\platforms\cpp""")
+        hiddenText("env.CPP_STAGING", """%PATH__WORKING_DIR%\cpp_staging""")
+    }
+
+    steps {
+        script {
+            name = "Build C++"
+            scriptContent = """
+                @echo on
+                
+                mkdir %PATH__CMAKE_BUILD_DIRECTORY%
+                cd %PATH__CMAKE_BUILD_DIRECTORY%
+                
+                cmake .. -DENABLE_TESTS=ON -DENABLE_ODBC=ON 
-DWARNINGS_AS_ERRORS=ON -DCMAKE_BUILD_TYPE=Debug 
-DCMAKE_INSTALL_PREFIX=%env.CPP_STAGING% -DCMAKE_CONFIGURATION_TYPES="Debug" -G 
"Visual Studio 15 2017" -A x64
+                
+                @echo off
+                if %%ERRORLEVEL%% NEQ 0 (
+                  echo 'CMake configuration failed'
+                  exit 5
+                )
+                @echo on
+                
+                cmake --build . -j8
+                
+                @echo off
+                if %%ERRORLEVEL%% NEQ 0 (
+                  echo 'CMake build failed'
+                  exit 6
+                )
+                @echo on
+                
+                cmake --install .
+                
+                @echo off
+                if %%ERRORLEVEL%% NEQ 0 (
+                  echo 'CMake install failed'
+                  exit 7
+                )
+                @echo on
+            """.trimIndent()
+        }
+        script {
+            name = "Unit tests"
+            workingDir = "%PATH__CMAKE_BUILD_DIRECTORY%"
+            scriptContent = """
+                ctest --version
+                ctest -E "(IgniteClientTest|IgniteOdbcTest)" --output-junit 
%PATH__UNIT_TESTS_RESULT%
+                exit 0
+            """.trimIndent()
+            formatStderrAsError = true
+        }
+        customGradle {
+            name = "Verify runner is builded"
+            tasks = ":ignite-runner:integrationTestClasses"
+        }
+        script {
+            name = "C++ Client integration tests"
+            workingDir = "%PATH__CMAKE_BUILD_DIRECTORY%"
+            scriptContent = """Debug\bin\ignite-client-test 
--gtest_output=xml:%PATH__CLIENT_TEST_RESULTS%"""
+            formatStderrAsError = true
+        }
+        script {
+            name = "ODBC integration tests"
+            enabled = false
+            workingDir = "%PATH__CMAKE_BUILD_DIRECTORY%"
+            scriptContent = """Debug\bin\ignite-odbc-test 
--gtest_output=xml:%PATH__ODBC_TEST_RESULTS%"""
+            formatStderrAsError = true
+        }
+    }
+
+    failureConditions {
+        executionTimeoutMin = 20
+        failOnMetricChange {
+            metric = BuildFailureOnMetric.MetricType.TEST_COUNT
+            threshold = 5
+            units = BuildFailureOnMetric.MetricUnit.DEFAULT_UNIT
+            comparison = BuildFailureOnMetric.MetricComparison.LESS
+            compareTo = build {
+                buildRule = lastSuccessful()
+            }
+        }
+        failOnText {
+            conditionType = BuildFailureOnText.ConditionType.CONTAINS
+            pattern = "CMake configuration failed"
+            failureMessage = "CMake configuration failed"
+            reverse = false
+        }
+        failOnText {
+            conditionType = BuildFailureOnText.ConditionType.CONTAINS
+            pattern = "CMake build failed"
+            failureMessage = "CMake build failed"
+            reverse = false
+        }
+        failOnText {
+            conditionType = BuildFailureOnText.ConditionType.CONTAINS
+            pattern = "CMake install failed"
+            failureMessage = "CMake install failed"
+            reverse = false
+        }
+    }
+
+    features {
+        xmlReport {
+            reportType = XmlReport.XmlReportType.GOOGLE_TEST
+            rules = """
+                +:%PATH__CLIENT_TEST_RESULTS%
+                +:%PATH__ODBC_TEST_RESULTS%
+                +:%PATH__CMAKE_BUILD_DIRECTORY%/Testing/Result/*.xml
+            """.trimIndent()
+            verbose = true
+        }
+        xmlReport {
+            reportType = XmlReport.XmlReportType.CTEST
+            rules = "+:%PATH__UNIT_TESTS_RESULT%"
+            verbose = true
+        }
+    }
+})
diff --git a/.teamcity/test/platform_tests/PlatformDotnetTestsLinux.kt 
b/.teamcity/test/platform_tests/PlatformDotnetTestsLinux.kt
new file mode 100644
index 00000000000..d73a37a2407
--- /dev/null
+++ b/.teamcity/test/platform_tests/PlatformDotnetTestsLinux.kt
@@ -0,0 +1,100 @@
+package test.platform_tests
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import jetbrains.buildServer.configs.kotlin.ParameterDisplay
+import jetbrains.buildServer.configs.kotlin.buildSteps.*
+import 
jetbrains.buildServer.configs.kotlin.failureConditions.BuildFailureOnText
+import jetbrains.buildServer.configs.kotlin.failureConditions.failOnText
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customScript
+import org.apache.ignite.teamcity.Teamcity
+
+
+object PlatformDotnetTestsLinux : BuildType({
+    id(Teamcity.getId(this::class))
+    name = "Platform .NET Tests (Linux)"
+
+    artifactRules = """
+        **/hs_err*.log => crashdumps.zip
+        **/*.hprof
+    """.trimIndent()
+
+    params {
+        text("PATH__WORKING_DIR", 
"%VCSROOT__IGNITE3%/modules/platforms/dotnet/", display = 
ParameterDisplay.HIDDEN, allowEmpty = true)
+        param("env.IGNITE_DOTNET_GRADLE_OPTS", "--no-daemon")
+    }
+
+    steps {
+        customScript(type = "bash") {
+            name = "Clean Up Remaining Processes"
+        }
+        script {
+            name = ".NET List SDKs"
+            scriptContent = "dotnet --list-sdks"
+        }
+        dotnetRestore {
+            name = ".NET Restore"
+            workingDir = "%PATH__WORKING_DIR%"
+        }
+        dotnetBuild {
+            name = ".NET Build (Debug)"
+            workingDir = "%PATH__WORKING_DIR%"
+            configuration = "Debug"
+            args = "--no-restore -m:1"
+        }
+        dotnetBuild {
+            name = ".NET Build (Release)"
+            workingDir = "%PATH__WORKING_DIR%"
+            configuration = "Release"
+            args = "--no-restore -m:1"
+        }
+        dotnetPack {
+            name = ".NET Pack (validate)"
+            workingDir = "%PATH__WORKING_DIR%"
+            configuration = "Release"
+            args = "--no-restore -m:8"
+        }
+        customGradle {
+            name = "Verify runner is built"
+            tasks = ":ignite-runner:integrationTestClasses 
:ignite-compatibility-tests:testFixturesClasses"
+        }
+        customScript(type = "bash") {
+            name = "Clean Up Remaining Processes"
+        }
+        dotnetTest {
+            name = ".NET Test (Debug)"
+            workingDir = "%PATH__WORKING_DIR%"
+            configuration = "Debug"
+            skipBuild = true
+            args = "-p:BuildInParallel=false -m:1"
+            sdk = "3.1 6"
+        }
+        customScript(type = "bash") {
+            name = "Clean Up Remaining Processes"
+        }
+        dotnetTest {
+            name = ".NET Test (Release)"
+            workingDir = "%PATH__WORKING_DIR%"
+            configuration = "Release"
+            skipBuild = true
+            args = "-p:BuildInParallel=false -m:1"
+            sdk = "3.1 6"
+        }
+        customScript(type = "bash") {
+            name = "Clean Up Remaining Processes"
+        }
+    }
+
+    failureConditions {
+        failOnText {
+            conditionType = BuildFailureOnText.ConditionType.CONTAINS
+            pattern = "NullReferenceException"
+            failureMessage = "NullReferenceException in log"
+            reverse = false
+        }
+    }
+
+    requirements {
+        equals("env.DIND_ENABLED", "true")
+    }
+})
diff --git a/.teamcity/test/platform_tests/PlatformDotnetTestsWindows.kt 
b/.teamcity/test/platform_tests/PlatformDotnetTestsWindows.kt
new file mode 100644
index 00000000000..2e087d9db95
--- /dev/null
+++ b/.teamcity/test/platform_tests/PlatformDotnetTestsWindows.kt
@@ -0,0 +1,94 @@
+package test.platform_tests
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import jetbrains.buildServer.configs.kotlin.ParameterDisplay
+import jetbrains.buildServer.configs.kotlin.buildFeatures.Swabra
+import jetbrains.buildServer.configs.kotlin.buildFeatures.swabra
+import jetbrains.buildServer.configs.kotlin.buildSteps.*
+import 
jetbrains.buildServer.configs.kotlin.failureConditions.BuildFailureOnText
+import jetbrains.buildServer.configs.kotlin.failureConditions.failOnText
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.Teamcity
+
+
+object PlatformDotnetTestsWindows : BuildType({
+    id(Teamcity.getId(this::class))
+    name = "Platform .NET Tests (Windows)"
+
+    artifactRules = """
+        **/hs_err*.log => crashdumps.zip
+        **/*.hprof
+    """.trimIndent()
+
+    params {
+        text("PATH__WORKING_DIR", 
"%VCSROOT__IGNITE3%/modules/platforms/dotnet/", display = 
ParameterDisplay.HIDDEN, allowEmpty = true)
+        param("env.IGNITE_DOTNET_GRADLE_OPTS", "--no-daemon")
+    }
+
+    steps {
+        script {
+            name = ".NET List SDKs"
+            scriptContent = "dotnet --list-sdks"
+        }
+        dotnetRestore {
+            name = ".NET Restore"
+            workingDir = "%PATH__WORKING_DIR%"
+        }
+        dotnetBuild {
+            name = ".NET Build (Debug)"
+            workingDir = "%PATH__WORKING_DIR%"
+            configuration = "Debug"
+            args = "--no-restore -m:1"
+        }
+        dotnetBuild {
+            name = ".NET Build (Release)"
+            workingDir = "%PATH__WORKING_DIR%"
+            configuration = "Release"
+            args = "--no-restore -m:1"
+        }
+        dotnetPack {
+            name = ".NET Pack (validate)"
+            workingDir = "%PATH__WORKING_DIR%"
+            configuration = "Release"
+            args = "--no-restore -m:8"
+        }
+        customGradle {
+            name = "Verify runner is built"
+            tasks = ":ignite-runner:integrationTestClasses 
:ignite-compatibility-tests:testFixturesClasses"
+        }
+        dotnetTest {
+            name = ".NET Test (Debug)"
+            workingDir = "%PATH__WORKING_DIR%"
+            configuration = "Debug"
+            skipBuild = true
+            args = "-p:BuildInParallel=false -m:1"
+            sdk = "3.1 6"
+        }
+        dotnetTest {
+            name = ".NET Test (Release)"
+            workingDir = "%PATH__WORKING_DIR%"
+            configuration = "Release"
+            skipBuild = true
+            args = "-p:BuildInParallel=false -m:1"
+            sdk = "3.1 6"
+        }
+    }
+
+    failureConditions {
+        executionTimeoutMin = 40
+        failOnText {
+            conditionType = BuildFailureOnText.ConditionType.CONTAINS
+            pattern = "NullReferenceException"
+            failureMessage = "NullReferenceException in log"
+            reverse = false
+        }
+    }
+
+    features {
+        swabra {
+            filesCleanup = Swabra.FilesCleanup.AFTER_BUILD
+            lockingProcesses = Swabra.LockingProcessPolicy.KILL
+            paths = """%VCSROOT__IGNITE3%\modules\compatibility-tests"""
+        }
+    }
+})
diff --git a/.teamcity/test/platform_tests/PlatformPythonTestsLinux.kt 
b/.teamcity/test/platform_tests/PlatformPythonTestsLinux.kt
new file mode 100644
index 00000000000..fa6f3fa86b0
--- /dev/null
+++ b/.teamcity/test/platform_tests/PlatformPythonTestsLinux.kt
@@ -0,0 +1,84 @@
+package test.platform_tests
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import jetbrains.buildServer.configs.kotlin.ParameterDisplay
+import jetbrains.buildServer.configs.kotlin.buildSteps.*
+import 
jetbrains.buildServer.configs.kotlin.failureConditions.BuildFailureOnMetric
+import 
jetbrains.buildServer.configs.kotlin.failureConditions.BuildFailureOnText
+import 
jetbrains.buildServer.configs.kotlin.failureConditions.failOnMetricChange
+import jetbrains.buildServer.configs.kotlin.failureConditions.failOnText
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.Teamcity
+
+
+object PlatformPythonTestsLinux : BuildType({
+    id(Teamcity.getId(this::class))
+    name = "Platform Python Tests (Linux)"
+
+    params {
+        text("PATH__WORKING_DIR", 
"""%VCSROOT__IGNITE3%\modules\platforms\python""", display = 
ParameterDisplay.HIDDEN, allowEmpty = true)
+        param("env.IGNITE_CPP_TESTS_USE_SINGLE_NODE", "")
+        param("env.CPP_STAGING", """%PATH__WORKING_DIR%\cpp_staging""")
+    }
+
+    steps {
+        customGradle {
+            name = "Verify runner is builded"
+            tasks = ":ignite-runner:integrationTestClasses"
+        }
+        script {
+            name = "Python Client tests"
+            workingDir = "%PATH__WORKING_DIR%"
+            scriptContent = """
+                #!/usr/bin/env bash
+                set -o errexit; set -o pipefail; set -o errtrace; set -o 
functrace
+                set -x
+                
+                
+                eval "${'$'}(pyenv init --path)" || echo 'first'
+                eval "${'$'}(pyenv init --no-rehash -)" || echo 'second'
+                
+                tox -e py39 || exit 0
+            """.trimIndent()
+        }
+    }
+
+    failureConditions {
+        executionTimeoutMin = 20
+        failOnMetricChange {
+            metric = BuildFailureOnMetric.MetricType.TEST_COUNT
+            threshold = 5
+            units = BuildFailureOnMetric.MetricUnit.DEFAULT_UNIT
+            comparison = BuildFailureOnMetric.MetricComparison.LESS
+            compareTo = build {
+                buildRule = lastSuccessful()
+            }
+        }
+        failOnText {
+            conditionType = BuildFailureOnText.ConditionType.CONTAINS
+            pattern = "CMake configuration failed"
+            failureMessage = "CMake configuration failed"
+            reverse = false
+        }
+        failOnText {
+            conditionType = BuildFailureOnText.ConditionType.CONTAINS
+            pattern = "CMake build failed"
+            failureMessage = "CMake build failed"
+            reverse = false
+        }
+        failOnText {
+            conditionType = BuildFailureOnText.ConditionType.CONTAINS
+            pattern = "CMake install failed"
+            failureMessage = "CMake install failed"
+            reverse = false
+        }
+    }
+
+    /**
+     *  Temporary lock Platform Linux jobs on old-type agents
+     *  until execution of these tests is fixed on DIND agents
+     */
+    requirements {
+        doesNotExist("env.DIND_ENABLED")
+    }
+})
diff --git a/.teamcity/test/platform_tests/Project.kt 
b/.teamcity/test/platform_tests/Project.kt
new file mode 100644
index 00000000000..1976d516a34
--- /dev/null
+++ b/.teamcity/test/platform_tests/Project.kt
@@ -0,0 +1,44 @@
+package test.platform_tests
+
+import jetbrains.buildServer.configs.kotlin.Project
+import org.apache.ignite.teamcity.ApacheIgnite3CustomBuildType
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+
+
+object Project : Project({
+    id(getId(this::class))
+    name = "[Platform Tests]"
+
+    /**
+     * List of platform linux tests
+     */
+
+    listOf(
+        PlatformCppTestsLinux,
+        PlatformDotnetTestsLinux,
+        PlatformPythonTestsLinux
+    ).forEach {
+        buildType(
+            ApacheIgnite3CustomBuildType.Builder(it)
+                .ignite3VCS().ignite3BuildDependency()
+                .defaultBuildTypeSettings().requireLinux()
+                .build().buildType
+        )
+    }
+
+    /**
+     * List of platform windows tests
+     */
+
+    listOf(
+        PlatformCppTestsWindows,
+        PlatformDotnetTestsWindows
+    ).forEach {
+        buildType(
+            ApacheIgnite3CustomBuildType.Builder(it)
+                .ignite3VCS().ignite3BuildDependency()
+                .defaultBuildTypeSettings().requireWindows()
+                .build().buildType
+        )
+    }
+})
diff --git a/.teamcity/test/sanity_check/Project.kt 
b/.teamcity/test/sanity_check/Project.kt
new file mode 100644
index 00000000000..217c0bd459e
--- /dev/null
+++ b/.teamcity/test/sanity_check/Project.kt
@@ -0,0 +1,27 @@
+package test.sanity_check
+
+import jetbrains.buildServer.configs.kotlin.Project
+import org.apache.ignite.teamcity.ApacheIgnite3CustomBuildType
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+import test.sanity_check.build_types.*
+
+object Project : Project({
+    id(getId(this::class))
+    name = "[Sanity Check]"
+
+    listOf(
+        AssembleTestClasses,
+        CodeStyle,
+        Javadoc,
+        MentionTicket,
+        PMD,
+        Spotbugs,
+    ).forEach {
+        buildType(
+            ApacheIgnite3CustomBuildType.Builder(it)
+                .ignite3VCS().ignite3BuildDependency()
+                .defaultBuildTypeSettings().requireLinux()
+                .build().buildType
+        )
+    }
+})
diff --git 
a/.teamcity/test/sanity_check/build_types/AssembleTestClassesJdk11.kt 
b/.teamcity/test/sanity_check/build_types/AssembleTestClassesJdk11.kt
new file mode 100644
index 00000000000..eec3d98ef23
--- /dev/null
+++ b/.teamcity/test/sanity_check/build_types/AssembleTestClassesJdk11.kt
@@ -0,0 +1,20 @@
+package test.sanity_check.build_types
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+
+object AssembleTestClasses : BuildType({
+    id(getId(this::class))
+    name = "Assemble testClasses [JDK11]"
+    description = "Assemble testClasses on JDK11"
+
+    steps {
+        customGradle {
+            name = "Assemble testClasses on JDK11"
+            tasks = "assemble testClasses"
+            jdkHome = "%env.JDK_ORA_11%"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+})
\ No newline at end of file
diff --git a/.teamcity/test/sanity_check/build_types/CodeStyle.kt 
b/.teamcity/test/sanity_check/build_types/CodeStyle.kt
new file mode 100644
index 00000000000..97a2110ed45
--- /dev/null
+++ b/.teamcity/test/sanity_check/build_types/CodeStyle.kt
@@ -0,0 +1,37 @@
+package test.sanity_check.build_types
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import 
jetbrains.buildServer.configs.kotlin.failureConditions.BuildFailureOnText
+import jetbrains.buildServer.configs.kotlin.failureConditions.failOnText
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+
+
+object CodeStyle : BuildType({
+    id(getId(this::class))
+    name = "Code Style"
+    description = "Check code's style rules with Checkstyle"
+
+    artifactRules = """
+        %VCSROOT__IGNITE3%/build/reports/checkstyle/*.html
+    """.trimIndent()
+
+    steps {
+        customGradle {
+            name = "Check code style by Checkstyle Gradle Plugin"
+            tasks = "checkstyle"
+            gradleParams = "--continue"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+
+    failureConditions {
+        executionTimeoutMin = 10
+        failOnText {
+            conditionType = BuildFailureOnText.ConditionType.REGEXP
+            pattern = "There.*[0-9]+ error(s)? reported by Checkstyle"
+            failureMessage = "CheckStyle errors"
+            reverse = false
+        }
+    }
+})
diff --git a/.teamcity/test/sanity_check/build_types/Javadoc.kt 
b/.teamcity/test/sanity_check/build_types/Javadoc.kt
new file mode 100644
index 00000000000..7e480e55f34
--- /dev/null
+++ b/.teamcity/test/sanity_check/build_types/Javadoc.kt
@@ -0,0 +1,36 @@
+package test.sanity_check.build_types
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customScript
+import 
org.apache.ignite.teamcity.CustomFailureConditions.Companion.failOnExactText
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+
+
+object Javadoc : BuildType({
+    id(getId(this::class))
+    name = "Javadoc"
+    description = "Check Javadoc correctness and style"
+
+    artifactRules = """
+        target/site/apidocs => javadoc.zip
+        target/checkstyle.xml
+        target/site/checkstyle-aggregate.html
+    """.trimIndent()
+
+    steps {
+        customGradle {
+            name = "Build Javadoc"
+            tasks = "aggregateJavadoc"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+
+        customScript(type = "bash") {
+            name = "Check internal packages"
+        }
+    }
+
+    failureConditions {
+        failOnExactText(pattern = "[ERROR] Internal packages detected", 
failureMessage = "[ERROR] Internal packages detected") {}
+    }
+})
diff --git a/.teamcity/test/sanity_check/build_types/MentionTicket.kt 
b/.teamcity/test/sanity_check/build_types/MentionTicket.kt
new file mode 100644
index 00000000000..2adf0dc564d
--- /dev/null
+++ b/.teamcity/test/sanity_check/build_types/MentionTicket.kt
@@ -0,0 +1,26 @@
+package test.sanity_check.build_types
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import jetbrains.buildServer.configs.kotlin.ParameterDisplay
+import jetbrains.buildServer.configs.kotlin.buildSteps.maven
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customScript
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+
+
+object MentionTicket : BuildType({
+    id(getId(this::class))
+    name = "Mention ticket"
+
+    steps {
+        customScript(type = "bash") {
+            name = "Check code base"
+            id = "CheckCodeBase"
+            workingDir = "%VCSROOT__IGNITE3%"
+
+            conditions {
+                equals("teamcity.build.branch.is_default", "false")
+            }
+        }
+    }
+})
diff --git a/.teamcity/test/sanity_check/build_types/PMD.kt 
b/.teamcity/test/sanity_check/build_types/PMD.kt
new file mode 100644
index 00000000000..ae6817020f7
--- /dev/null
+++ b/.teamcity/test/sanity_check/build_types/PMD.kt
@@ -0,0 +1,22 @@
+package test.sanity_check.build_types
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+
+
+object PMD : BuildType({
+    id(getId(this::class))
+    name = "PMD"
+    description = "Check possible bugs on code using PMD"
+
+    artifactRules = "**/build/reports/pmd/*"
+
+    steps {
+        customGradle {
+            name = "PMD check"
+            tasks = "pmdMain pmdTest"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+})
diff --git a/.teamcity/test/sanity_check/build_types/Spotbugs.kt 
b/.teamcity/test/sanity_check/build_types/Spotbugs.kt
new file mode 100644
index 00000000000..ca5bcd03b8f
--- /dev/null
+++ b/.teamcity/test/sanity_check/build_types/Spotbugs.kt
@@ -0,0 +1,19 @@
+package test.sanity_check.build_types
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.Teamcity
+
+object Spotbugs: BuildType({
+    id(Teamcity.getId(this::class))
+    name = "Spotbugs"
+    description = "Static analysis of source code via Spotbugs"
+
+    steps {
+        customGradle {
+            name = "Static analysis of source code via Spotbugs"
+            tasks = "spotbugsMain"
+            workingDir = "%VCSROOT__IGNITE3%"
+        }
+    }
+})
\ No newline at end of file
diff --git a/.teamcity/test/template_types/GradleModule.kt 
b/.teamcity/test/template_types/GradleModule.kt
new file mode 100644
index 00000000000..65216b1c0d7
--- /dev/null
+++ b/.teamcity/test/template_types/GradleModule.kt
@@ -0,0 +1,9 @@
+package test.template_types
+
+data class GradleModule(val displayName: String, val moduleName: String, val 
jvmArgs: String = "", val dependencies: List<String> = emptyList()) {
+    fun buildTask(taskName: String): String {
+        val dependencyTasks = dependencies.joinToString(" ")
+        val mainTask = ":$moduleName:$taskName"
+        return if (dependencyTasks.isNotEmpty()) "$dependencyTasks $mainTask" 
else mainTask
+    }
+}
diff --git a/.teamcity/test/template_types/OtherTestsModule.kt 
b/.teamcity/test/template_types/OtherTestsModule.kt
new file mode 100644
index 00000000000..4fd7469abc7
--- /dev/null
+++ b/.teamcity/test/template_types/OtherTestsModule.kt
@@ -0,0 +1,64 @@
+package test.template_types
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import 
jetbrains.buildServer.configs.kotlin.failureConditions.BuildFailureOnText
+import jetbrains.buildServer.configs.kotlin.failureConditions.failOnText
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customScript
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+import org.apache.ignite.teamcity.Teamcity.Companion.hiddenText
+
+
+class OtherTestsModule(
+    private val configuration: TestConfiguration,
+    private val excludeModules: List<GradleModule>,
+    private val jvmArgs: String = ""
+): BuildType({
+    id(getId(this::class, "${configuration.suiteId} All_Other_Tests", true))
+    name = configuration.suiteId + " All_Other_Tests"
+
+    artifactRules = """
+        %VCSROOT__IGNITE3%/build/reports/**/index.html
+    """.trimIndent()
+
+    params {
+        hiddenText("XMX", configuration.xmx.toString() + "g")
+        hiddenText("JVM_ARGS", jvmArgs + configuration.jvmArg)
+
+        hiddenText("IGNITE_COMPATIBILITY_TEST_ALL_VERSIONS", 
"-DtestAllVersions=false")
+        hiddenText("IGNITE_ZONE_BASED_REPLICATION", 
"-DIGNITE_ZONE_BASED_REPLICATION=true")
+        hiddenText("IGNITE_DEFAULT_STORAGE_ENGINE", "")
+        hiddenText("env.GRADLE_OPTS", 
"-PextraJvmArgs=\"%IGNITE_COMPATIBILITY_TEST_ALL_VERSIONS% 
%IGNITE_ZONE_BASED_REPLICATION% %IGNITE_DEFAULT_STORAGE_ENGINE%\"")
+    }
+
+    steps {
+        customScript(type = "bash") {
+            name = "Clean Up Remaining Processes"
+        }
+
+        customGradle {
+            id = "RunTests"
+            name = "Run tests"
+            tasks = configuration.testTask + " " +
+                excludeModules.map { "-x " + 
it.buildTask(configuration.testTask) }.joinToString(" ")
+            workingDir = "%VCSROOT__IGNITE3%"
+            gradleParams = "%env.GRADLE_OPTS%"
+            this.jvmArgs = """
+                -Xmx%XMX%
+                %JVM_ARGS%
+            """.trimIndent()
+        }
+
+        customScript(type = "bash") {
+            name = "Clean Up Remaining Processes"
+        }
+    }
+
+    failureConditions {
+        executionTimeoutMin = configuration.executionTimeoutMin
+    }
+
+    requirements {
+        if (configuration.dindSupport) equals("env.DIND_ENABLED", "true") else 
{}
+    }
+})
diff --git a/.teamcity/test/template_types/RunTests.kt 
b/.teamcity/test/template_types/RunTests.kt
new file mode 100644
index 00000000000..94c7098dfbe
--- /dev/null
+++ b/.teamcity/test/template_types/RunTests.kt
@@ -0,0 +1,22 @@
+package test.template_types
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+import test.build_types.RunSanityCheck
+
+class RunTests(private val tests: Tests, private val suiteId: String = 
tests.configuration.suiteId) : BuildType({
+    name = "> Run :: $suiteId Tests"
+    type = Type.COMPOSITE
+    id(getId(this::class, name, true))
+
+    dependencies {
+        snapshot(RunSanityCheck) {}
+
+        for (test in tests.modules) {
+            snapshot(TestsModule(tests.configuration, test)) {}
+        }
+        if (tests.enableOthers) {
+            snapshot(OtherTestsModule(tests.configuration, tests.modules)) {}
+        }
+    }
+})
diff --git a/.teamcity/test/template_types/RunTestsList.kt 
b/.teamcity/test/template_types/RunTestsList.kt
new file mode 100644
index 00000000000..d69c8e5e788
--- /dev/null
+++ b/.teamcity/test/template_types/RunTestsList.kt
@@ -0,0 +1,21 @@
+package test.template_types
+
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+
+class RunTestsList(private val testsList: List<Tests>, private val suiteId: 
String) : BuildType({
+    name = "> Run :: $suiteId Tests"
+    type = Type.COMPOSITE
+    id(getId(this::class, name, true))
+
+    dependencies {
+        for (tests in testsList) {
+            for (test in tests.modules) {
+                snapshot(TestsModule(tests.configuration, test)) {}
+            }
+            if (tests.enableOthers) {
+                snapshot(OtherTestsModule(tests.configuration, tests.modules)) 
{}
+            }
+        }
+    }
+})
diff --git a/.teamcity/test/template_types/TestConfiguration.kt 
b/.teamcity/test/template_types/TestConfiguration.kt
new file mode 100644
index 00000000000..26e01103357
--- /dev/null
+++ b/.teamcity/test/template_types/TestConfiguration.kt
@@ -0,0 +1,9 @@
+package test.template_types
+
+data class TestConfiguration(
+    val suiteId: String,
+    val testTask: String,
+    val xmx: Int = 2,
+    val executionTimeoutMin: Int = 30,
+    val jvmArg: String = "",
+    val dindSupport: Boolean = false)
\ No newline at end of file
diff --git a/.teamcity/test/template_types/Tests.kt 
b/.teamcity/test/template_types/Tests.kt
new file mode 100644
index 00000000000..b68e0413bb0
--- /dev/null
+++ b/.teamcity/test/template_types/Tests.kt
@@ -0,0 +1,33 @@
+package test.template_types
+
+import org.apache.ignite.teamcity.ApacheIgnite3CustomBuildType
+import jetbrains.buildServer.configs.kotlin.BuildType
+
+data class Tests(
+    val configuration: TestConfiguration,
+    val modules: List<GradleModule>,
+    val enableOthers: Boolean = true,
+    val excludeOnlyModules: List<GradleModule> = emptyList(),
+) {
+
+    fun buildType(): List<BuildType> {
+        val map = modules.map {
+            ApacheIgnite3CustomBuildType.Builder(TestsModule(configuration, 
it))
+                .ignite3VCS().ignite3BuildDependency()
+                .defaultBuildTypeSettings().requireLinux()
+                .testsFailureCondition()
+                .build().buildType
+        }
+
+        if (enableOthers) {
+            val otherModules = 
ApacheIgnite3CustomBuildType.Builder(OtherTestsModule(configuration, modules + 
excludeOnlyModules))
+                .ignite3VCS().ignite3BuildDependency()
+                .defaultBuildTypeSettings().requireLinux()
+                .testsFailureCondition()
+                .build().buildType
+
+            return map + otherModules
+        }
+        return map
+    }
+}
\ No newline at end of file
diff --git a/.teamcity/test/template_types/TestsModule.kt 
b/.teamcity/test/template_types/TestsModule.kt
new file mode 100644
index 00000000000..97cd94533f3
--- /dev/null
+++ b/.teamcity/test/template_types/TestsModule.kt
@@ -0,0 +1,66 @@
+package test.template_types
+
+import jetbrains.buildServer.configs.kotlin.BuildStep
+import jetbrains.buildServer.configs.kotlin.BuildType
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customGradle
+import org.apache.ignite.teamcity.CustomBuildSteps.Companion.customScript
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+import org.apache.ignite.teamcity.Teamcity.Companion.hiddenText
+
+
+class TestsModule(
+    private val configuration: TestConfiguration,
+    private val module: GradleModule
+) : BuildType({
+    id(getId(this::class, "${configuration.suiteId} 
Tests_${module.displayName}", true))
+    name = configuration.suiteId + " " + module.displayName
+
+    artifactRules = """
+        ignite-3/modules/${module.moduleName}/build/reports/**/index.html
+    """.trimIndent()
+
+    params {
+        hiddenText("XMX", configuration.xmx.toString() + "g")
+        hiddenText("JVM_ARGS", module.jvmArgs + configuration.jvmArg)
+
+        hiddenText("IGNITE_COMPATIBILITY_TEST_ALL_VERSIONS", 
"-DtestAllVersions=false")
+        hiddenText("IGNITE_ZONE_BASED_REPLICATION", 
"-DIGNITE_ZONE_BASED_REPLICATION=true")
+        hiddenText("IGNITE_DEFAULT_STORAGE_ENGINE", "")
+        hiddenText("env.GRADLE_OPTS", 
"-PextraJvmArgs=\"%IGNITE_COMPATIBILITY_TEST_ALL_VERSIONS% 
%IGNITE_ZONE_BASED_REPLICATION% %IGNITE_DEFAULT_STORAGE_ENGINE%\"")
+    }
+
+    steps {
+        customScript(type = "bash") {
+            name = "Clean Up Remaining Processes"
+        }
+        customGradle {
+            name = "Run tests"
+            tasks = module.buildTask(configuration.testTask)
+            workingDir = "%VCSROOT__IGNITE3%"
+            gradleParams = "%env.GRADLE_OPTS%"
+            jvmArgs = """
+                -Xmx%XMX%
+                %JVM_ARGS%
+            """.trimIndent()
+        }
+        customScript(type = "bash") {
+            name = "Clean Up Remaining Processes"
+        }
+        customScript(type = "bash") {
+            id = "PruneDockerImages"
+            name = "DockerImagePrune"
+            executionMode = BuildStep.ExecutionMode.ALWAYS
+            conditions {
+                equals("env.DIND_ENABLED", "true")
+            }
+        }
+    }
+
+    failureConditions {
+        executionTimeoutMin = configuration.executionTimeoutMin
+    }
+
+    requirements {
+        if (configuration.dindSupport) equals("env.DIND_ENABLED", "true") else 
{}
+    }
+})
diff --git a/.teamcity/test/unit_tests/Project.kt 
b/.teamcity/test/unit_tests/Project.kt
new file mode 100644
index 00000000000..6293d50d171
--- /dev/null
+++ b/.teamcity/test/unit_tests/Project.kt
@@ -0,0 +1,13 @@
+package test.unit_tests
+
+import jetbrains.buildServer.configs.kotlin.Project
+import org.apache.ignite.teamcity.ApacheIgnite3Teamcity.Companion.UNIT
+import org.apache.ignite.teamcity.Teamcity.Companion.getId
+
+
+object Project : Project({
+    id(getId(this::class))
+    name = "[Unit Tests]"
+
+    UNIT.buildType().forEach { buildType(it) }
+})
diff --git a/build.gradle b/build.gradle
index 8c75e127de9..771226520c1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -76,6 +76,13 @@ ext {
     }
 }
 
+def trimQuotes(String input) {
+    if (input.startsWith("\"") && input.endsWith("\"") && input.length() > 2) {
+        return input.substring(1, input.length() - 1);
+    }
+    return input;
+}
+
 allprojects {
     group 'org.apache.ignite'
     version = projectVersion
@@ -89,11 +96,11 @@ allprojects {
         def extraJvmArgs = []
 
         if (project.hasProperty('extraJvmArgs')) {
-            extraJvmArgs = project.property('extraJvmArgs')
-                .toString()
-                .trim()
-                .split(/\s+/)  // Split on whitespace
-                .toList()
+            def prop = project.property('extraJvmArgs').toString().trim()
+
+            extraJvmArgs = trimQuotes(prop)
+                    .split(/\s+/)  // Split on whitespace
+                    .toList()
         }
 
         jvmArgs += defaultJvmArgs + extraJvmArgs

Reply via email to