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

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


The following commit(s) were added to refs/heads/ignite-9800 by this push:
     new f40fdba  IGNITE-9800: Github integration refactored to standalone 
module
f40fdba is described below

commit f40fdba2854e70e5976c622871c44173a9c20f42
Author: Dmitriy Pavlov <[email protected]>
AuthorDate: Fri Oct 5 18:16:38 2018 +0300

    IGNITE-9800: Github integration refactored to standalone module
---
 .../java/org/apache/ignite/ci/HelperConfig.java    |   4 +-
 .../org/apache/ignite/ci/ITcServerProvider.java    |   2 +-
 .../main/java/org/apache/ignite/ci/ITeamcity.java  |  40 +---
 .../apache/ignite/ci/IgnitePersistentTeamcity.java |  29 ---
 .../apache/ignite/ci/IgniteTeamcityConnection.java |  75 +------
 .../apache/ignite/ci/chain/PrChainsProcessor.java  |   7 +-
 .../org/apache/ignite/ci/di/IgniteTcBotModule.java |   2 +
 .../ignite/ci/github/GitHubCachingProvider.java    |  59 +++++
 .../ignite/ci/github/GitHubConnectionImpl.java     | 113 ++++++++++
 .../GitHubIntegrationModule.java}                  |  18 +-
 .../IGitHubConnection.java}                        |  35 ++-
 .../IGitHubConnectionProvider.java}                |  16 +-
 .../TcBotTriggerAndSignOffService.java}            | 238 +++++++--------------
 .../ignite/ci/web/model/current/UpdateInfo.java    |   7 +-
 .../apache/ignite/ci/web/rest/TriggerBuild.java    | 148 ++-----------
 .../ignite/ci/web/rest/pr/GetPrTestFailures.java   |  11 +-
 16 files changed, 343 insertions(+), 461 deletions(-)

diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/HelperConfig.java 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/HelperConfig.java
index c39fd1e..0b6b0a8 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/HelperConfig.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/HelperConfig.java
@@ -100,7 +100,7 @@ public class HelperConfig {
         return props;
     }
 
-    static String prepareConfigName(String tcName) {
+    public static String prepareConfigName(String tcName) {
         return prefixedWithServerName(tcName, CONFIG_FILE_NAME);
     }
 
@@ -136,7 +136,7 @@ public class HelperConfig {
      * @param props Properties, where token is placed.
      * @return Null or decoded auth token for Github.
      */
-    @Nullable static String prepareGithubHttpAuthToken(Properties props) {
+    @Nullable public static String prepareGithubHttpAuthToken(Properties 
props) {
         String tok = props.getProperty(GITHUB_AUTH_TOKEN);
 
         if (isNullOrEmpty(tok))
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcServerProvider.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcServerProvider.java
index 96d4ad1..702ca22 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcServerProvider.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcServerProvider.java
@@ -24,5 +24,5 @@ import javax.annotation.Nullable;
  * Provides instance to server with appropriate credentials, may cache 
instances to avoid odd server instances.
  */
 public interface ITcServerProvider {
-    IAnalyticsEnabledTeamcity server(String srvId, @Nullable ICredentialsProv 
prov);
+    public IAnalyticsEnabledTeamcity server(String srvId, @Nullable 
ICredentialsProv prov);
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITeamcity.java 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITeamcity.java
index e404b70..34b84b0 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITeamcity.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITeamcity.java
@@ -29,7 +29,6 @@ import org.apache.ignite.ci.analysis.LogCheckResult;
 import org.apache.ignite.ci.analysis.MultBuildRunCtx;
 import org.apache.ignite.ci.analysis.SingleBuildRunCtx;
 import org.apache.ignite.ci.chain.BuildChainProcessor;
-import org.apache.ignite.ci.github.PullRequest;
 import org.apache.ignite.ci.tcmodel.agent.Agent;
 import org.apache.ignite.ci.tcmodel.changes.Change;
 import org.apache.ignite.ci.tcmodel.changes.ChangeRef;
@@ -275,15 +274,6 @@ public interface ITeamcity {
      */
     boolean isTeamCityTokenAvailable();
 
-    /**
-     * @param token GitHub authorization token.
-     */
-    void setGitToken(String token);
-
-    /**
-     * @return {@code True} if GitHub authorization token is available.
-     */
-    boolean isGitTokenAvailable();
 
     /**
      * @param tok Jira authorization token.
@@ -296,21 +286,6 @@ public interface ITeamcity {
     boolean isJiraTokenAvailable();
 
     /**
-     * Send POST request with given body.
-     *
-     * @param url Url.
-     * @param body Request body.
-     * @return {@code True} - if GitHub was notified. {@code False} - 
otherwise.
-     */
-    boolean notifyGit(String url, String body);
-
-    /**
-     * @param branch TeamCity's branch name. Looks like "pull/123/head".
-     * @return Pull Request.
-     */
-    PullRequest getPullRequest(String branch);
-
-    /**
      * @param ticket JIRA ticket full name.
      * @param comment Comment to be placed in the ticket conversation.
      * @return {@code True} if ticket was succesfully commented. Otherwise - 
{@code false}.
@@ -321,16 +296,6 @@ public interface ITeamcity {
     String sendJiraComment(String ticket, String comment) throws IOException;
 
     /**
-     * @param url URL for git integration.
-     */
-    void setGitApiUrl(String url);
-
-    /**
-     * @return URL for git integration.
-     */
-    String getGitApiUrl();
-
-    /**
      * @param url URL for JIRA integration.
      */
     void setJiraApiUrl(String url);
@@ -340,9 +305,9 @@ public interface ITeamcity {
      */
     String getJiraApiUrl();
 
-    default void setAuthData(String user, String password) {
+    default void setAuthData(String user, String pwd) {
         setAuthToken(
-                Base64Util.encodeUtf8String(user + ":" + password));
+                Base64Util.encodeUtf8String(user + ":" + pwd));
     }
 
     /**
@@ -357,4 +322,5 @@ public interface ITeamcity {
     void init(String serverId);
 
     User getUserByUsername(String username);
+
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java
index 35e5d63..83d5a4a 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java
@@ -1143,16 +1143,6 @@ public class IgnitePersistentTeamcity implements 
IAnalyticsEnabledTeamcity, ITea
     }
 
     /** {@inheritDoc} */
-    @Override public void setGitToken(String tok) {
-        teamcity.setGitToken(tok);
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean isGitTokenAvailable() {
-        return teamcity.isGitTokenAvailable();
-    }
-
-    /** {@inheritDoc} */
     @Override public void setJiraToken(String tok) {
         teamcity.setJiraToken(tok);
     }
@@ -1167,15 +1157,6 @@ public class IgnitePersistentTeamcity implements 
IAnalyticsEnabledTeamcity, ITea
         return teamcity.sendJiraComment(ticket, comment);
     }
 
-    /** {@inheritDoc} */
-    @Override public void setGitApiUrl(String url) {
-        teamcity.setGitApiUrl(url);
-    }
-
-    /** {@inheritDoc} */
-    @Override public String getGitApiUrl() {
-        return teamcity.getGitApiUrl();
-    }
 
     /** {@inheritDoc} */
     @Override public void setJiraApiUrl(String url) {
@@ -1188,16 +1169,6 @@ public class IgnitePersistentTeamcity implements 
IAnalyticsEnabledTeamcity, ITea
     }
 
     /** {@inheritDoc} */
-    @Override public PullRequest getPullRequest(String branchForTc) {
-        return teamcity.getPullRequest(branchForTc);
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean notifyGit(String url, String body) {
-        return teamcity.notifyGit(url, body);
-    }
-
-    /** {@inheritDoc} */
     @Override public List<Agent> agents(boolean connected, boolean authorized) 
{
         return teamcity.agents(connected, authorized);
     }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java
index aa0e76c..ee85668 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java
@@ -111,15 +111,9 @@ public class IgniteTeamcityConnection implements ITeamcity 
{
     /** Teamcity http connection. */
     @Inject private ITeamcityHttpConnection teamcityHttpConn;
 
-    /** GitHub authorization token.  */
-    private String gitAuthTok;
-
     /**  JIRA authorization token. */
     private String jiraBasicAuthTok;
 
-    /** URL for git integration. */
-    private String gitApiUrl;
-
     /** URL for JIRA integration. */
     private String jiraApiUrl;
 
@@ -129,6 +123,7 @@ public class IgniteTeamcityConnection implements ITeamcity {
     /** Build logger processing running. */
     private ConcurrentHashMap<Integer, CompletableFuture<LogCheckTask>> 
buildLogProcessingRunning = new ConcurrentHashMap<>();
 
+    /** {@inheritDoc} */
     public void init(@Nullable String tcName) {
         this.tcName = tcName;
         final File workDir = HelperConfig.resolveWorkDir();
@@ -149,9 +144,6 @@ public class IgniteTeamcityConnection implements ITeamcity {
             logger.error("Failed to set credentials", e);
         }
 
-        setGitToken(HelperConfig.prepareGithubHttpAuthToken(props));
-        setGitApiUrl(props.getProperty(HelperConfig.GIT_API_URL));
-
         setJiraToken(HelperConfig.prepareJiraHttpAuthToken(props));
         setJiraApiUrl(props.getProperty(HelperConfig.JIRA_API_URL));
 
@@ -173,16 +165,6 @@ public class IgniteTeamcityConnection implements ITeamcity 
{
     }
 
     /** {@inheritDoc} */
-    @Override public void setGitToken(String tok) {
-        gitAuthTok = tok;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean isGitTokenAvailable() {
-        return gitAuthTok != null;
-    }
-
-    /** {@inheritDoc} */
     @Override public void setJiraToken(String tok) {
         jiraBasicAuthTok = tok;
     }
@@ -204,16 +186,6 @@ public class IgniteTeamcityConnection implements ITeamcity 
{
     }
 
     /** {@inheritDoc} */
-    @Override public void setGitApiUrl(String url) {
-        gitApiUrl = url;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String getGitApiUrl() {
-        return gitApiUrl;
-    }
-
-    /** {@inheritDoc} */
     @Override public void setJiraApiUrl(String url) {
         jiraApiUrl = url;
     }
@@ -223,51 +195,6 @@ public class IgniteTeamcityConnection implements ITeamcity 
{
         return jiraApiUrl;
     }
 
-    /** {@inheritDoc} */
-    @AutoProfiling
-    @Override public PullRequest getPullRequest(String branchForTc) {
-        if (isNullOrEmpty(gitApiUrl))
-            throw new IllegalStateException("Git API URL is not configured for 
this server.");
-
-        String id = null;
-
-        // Get PR id from string "pull/XXXX/head"
-        for (int i = 5; i < branchForTc.length(); i++) {
-            char c = branchForTc.charAt(i);
-
-            if (!Character.isDigit(c)) {
-                id = branchForTc.substring(5, i);
-
-                break;
-            }
-        }
-
-        String pr = gitApiUrl + "pulls/" + id;
-
-        try (InputStream is = HttpUtil.sendGetToGit(gitAuthTok, pr)) {
-            InputStreamReader reader = new InputStreamReader(is);
-
-            return new Gson().fromJson(reader, PullRequest.class);
-        }
-        catch (IOException e) {
-            throw new UncheckedIOException(e);
-        }
-    }
-
-    /** {@inheritDoc} */
-    @AutoProfiling
-    @Override public boolean notifyGit(String url, String body) {
-        try {
-            HttpUtil.sendPostAsStringToGit(gitAuthTok, url, body);
-
-            return true;
-        }
-        catch (IOException e) {
-            logger.error("Failed to notify Git [errMsg="+e.getMessage()+']');
-
-            return false;
-        }
-    }
 
     /** {@inheritDoc} */
     @AutoProfiling
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/chain/PrChainsProcessor.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/chain/PrChainsProcessor.java
index 8e2030e..926967e 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/chain/PrChainsProcessor.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/chain/PrChainsProcessor.java
@@ -24,6 +24,8 @@ import org.apache.ignite.ci.analysis.FullChainRunCtx;
 import org.apache.ignite.ci.analysis.mode.LatestRebuildMode;
 import org.apache.ignite.ci.analysis.mode.ProcessLogsMode;
 import org.apache.ignite.ci.di.AutoProfiling;
+import org.apache.ignite.ci.github.IGitHubConnection;
+import org.apache.ignite.ci.github.IGitHubConnectionProvider;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.user.ICredentialsProv;
 import org.apache.ignite.ci.web.model.current.ChainAtServerCurrentStatus;
@@ -47,6 +49,7 @@ public class PrChainsProcessor {
 
     /** Tc server provider. */
     @Inject ITcServerProvider tcSrvProvider;
+    @Inject IGitHubConnectionProvider gitHubConnectionProvider;
 
     /**
      * @param creds Credentials.
@@ -75,7 +78,9 @@ public class PrChainsProcessor {
         //using here non persistent TC allows to skip update statistic
         IAnalyticsEnabledTeamcity teamcity = tcSrvProvider.server(srvId, 
creds);
 
-        res.setJavaFlags(teamcity);
+        IGitHubConnection gitHubConnection = 
gitHubConnectionProvider.server(srvId, creds);
+
+        res.setJavaFlags(teamcity, gitHubConnection);
 
         LatestRebuildMode rebuild;
         if (FullQueryParams.HISTORY.equals(act))
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/IgniteTcBotModule.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/IgniteTcBotModule.java
index 5445dc0..c0b0215 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/IgniteTcBotModule.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/IgniteTcBotModule.java
@@ -25,6 +25,7 @@ import com.google.inject.matcher.Matchers;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.ci.*;
 import org.apache.ignite.ci.db.Ignite1Init;
+import org.apache.ignite.ci.github.GitHubIntegrationModule;
 import org.apache.ignite.ci.issue.IssueDetector;
 import org.apache.ignite.ci.jira.IJiraIntegration;
 import org.apache.ignite.ci.observer.BuildObserver;
@@ -81,6 +82,7 @@ public class IgniteTcBotModule extends AbstractModule {
 
         bind(BackgroundUpdater.class).in(new SingletonScope());
         install(new TcRealConnectionModule());
+        install(new GitHubIntegrationModule());
     }
 
     //todo fallback to TC big class
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/GitHubCachingProvider.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/GitHubCachingProvider.java
new file mode 100644
index 0000000..f0b37d0
--- /dev/null
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/GitHubCachingProvider.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ignite.ci.github;
+
+import com.google.common.base.Strings;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+import javax.inject.Provider;
+import org.apache.ignite.ci.user.ICredentialsProv;
+import org.apache.ignite.ci.util.ExceptionUtil;
+
+class GitHubCachingProvider implements IGitHubConnectionProvider {
+    @Inject Provider<IGitHubConnection> factory;
+    private final Cache<String, IGitHubConnection> srvs
+        = CacheBuilder.newBuilder()
+        .maximumSize(100)
+        .expireAfterAccess(16, TimeUnit.MINUTES)
+        .softValues()
+        .build();
+
+    /** {@inheritDoc} */
+    @Override public IGitHubConnection server(String srvId, @Nullable 
ICredentialsProv prov) {
+        Callable<IGitHubConnection> call = () -> {
+            IGitHubConnection conn = factory.get();
+            conn.init(srvId);
+            return conn;
+        };
+        String fullKey = Strings.nullToEmpty(srvId);
+
+        IGitHubConnection gitHubConn;
+        try {
+            gitHubConn = srvs.get(fullKey, call);
+        }
+        catch (ExecutionException e) {
+            throw ExceptionUtil.propagateException(e);
+        }
+        return gitHubConn;
+    }
+
+}
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/GitHubConnectionImpl.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/GitHubConnectionImpl.java
new file mode 100644
index 0000000..adb7fc1
--- /dev/null
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/GitHubConnectionImpl.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ignite.ci.github;
+
+import com.google.gson.Gson;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UncheckedIOException;
+import java.util.Properties;
+import org.apache.ignite.ci.HelperConfig;
+import org.apache.ignite.ci.di.AutoProfiling;
+import org.apache.ignite.ci.util.HttpUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+
+class GitHubConnectionImpl implements IGitHubConnection {
+    /** Logger. */
+    private static final Logger logger = 
LoggerFactory.getLogger(GitHubConnectionImpl.class);
+
+    /** URL for git integration. */
+    private String gitApiUrl;
+
+    /** GitHub authorization token. */
+    private String gitAuthTok;
+
+    /** {@inheritDoc} */
+    @Override public void init(String srvId) {
+        final File workDir = HelperConfig.resolveWorkDir();
+
+        String cfgName = HelperConfig.prepareConfigName(srvId);
+
+        final Properties props = HelperConfig.loadAuthProperties(workDir, 
cfgName);
+
+        gitAuthTok = (HelperConfig.prepareGithubHttpAuthToken(props));
+        gitApiUrl = (props.getProperty(HelperConfig.GIT_API_URL));
+    }
+
+    /** {@inheritDoc} */
+    @AutoProfiling
+    @Override public PullRequest getPullRequest(String branchForTc) {
+        if (isNullOrEmpty(gitApiUrl))
+            throw new IllegalStateException("Git API URL is not configured for 
this server.");
+
+        String id = null;
+
+        // Get PR id from string "pull/XXXX/head"
+        for (int i = 5; i < branchForTc.length(); i++) {
+            char c = branchForTc.charAt(i);
+
+            if (!Character.isDigit(c)) {
+                id = branchForTc.substring(5, i);
+
+                break;
+            }
+        }
+
+        String pr = gitApiUrl + "pulls/" + id;
+
+        try (InputStream is = HttpUtil.sendGetToGit(gitAuthTok, pr)) {
+            InputStreamReader reader = new InputStreamReader(is);
+
+            return new Gson().fromJson(reader, PullRequest.class);
+        }
+        catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @AutoProfiling
+    @Override public boolean notifyGit(String url, String body) {
+        try {
+            HttpUtil.sendPostAsStringToGit(gitAuthTok, url, body);
+
+            return true;
+        }
+        catch (IOException e) {
+            logger.error("Failed to notify Git [errMsg="+e.getMessage()+']');
+
+            return false;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isGitTokenAvailable() {
+        return gitAuthTok != null;
+    }
+
+    /**
+     * @return URL for git integration.
+     */
+    public String gitApiUrl() {
+        return gitApiUrl;
+    }
+}
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcServerProvider.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/GitHubIntegrationModule.java
similarity index 64%
copy from 
ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcServerProvider.java
copy to 
ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/GitHubIntegrationModule.java
index 96d4ad1..8251898 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcServerProvider.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/GitHubIntegrationModule.java
@@ -14,15 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.ignite.ci;
+package org.apache.ignite.ci.github;
 
-import org.apache.ignite.ci.user.ICredentialsProv;
+import com.google.inject.AbstractModule;
+import com.google.inject.internal.SingletonScope;
 
-import javax.annotation.Nullable;
-
-/**
- * Provides instance to server with appropriate credentials, may cache 
instances to avoid odd server instances.
- */
-public interface ITcServerProvider {
-    IAnalyticsEnabledTeamcity server(String srvId, @Nullable ICredentialsProv 
prov);
+public class GitHubIntegrationModule extends AbstractModule {
+    /** {@inheritDoc} */
+    @Override protected void configure() {
+        bind(IGitHubConnection.class).to(GitHubConnectionImpl.class);
+        
bind(IGitHubConnectionProvider.class).to(GitHubCachingProvider.class).in(new 
SingletonScope());
+    }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcServerProvider.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/IGitHubConnection.java
similarity index 52%
copy from 
ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcServerProvider.java
copy to 
ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/IGitHubConnection.java
index 96d4ad1..a510c73 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcServerProvider.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/IGitHubConnection.java
@@ -14,15 +14,34 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.ignite.ci;
+package org.apache.ignite.ci.github;
 
-import org.apache.ignite.ci.user.ICredentialsProv;
+public interface IGitHubConnection {
 
-import javax.annotation.Nullable;
+    void init(String srvId);
 
-/**
- * Provides instance to server with appropriate credentials, may cache 
instances to avoid odd server instances.
- */
-public interface ITcServerProvider {
-    IAnalyticsEnabledTeamcity server(String srvId, @Nullable ICredentialsProv 
prov);
+    /**
+     * @param branch TeamCity's branch name. Looks like "pull/123/head".
+     * @return Pull Request.
+     */
+    PullRequest getPullRequest(String branch);
+
+    /**
+     * Send POST request with given body.
+     *
+     * @param url Url.
+     * @param body Request body.
+     * @return {@code True} - if GitHub was notified. {@code False} - 
otherwise.
+     */
+    boolean notifyGit(String url, String body);
+
+    /**
+     * @return {@code True} if GitHub authorization token is available.
+     */
+    boolean isGitTokenAvailable();
+
+    /**
+     * @return URL for git integration.
+     */
+    String gitApiUrl();
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcServerProvider.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/IGitHubConnectionProvider.java
similarity index 76%
copy from 
ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcServerProvider.java
copy to 
ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/IGitHubConnectionProvider.java
index 96d4ad1..8c3f66d 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcServerProvider.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/IGitHubConnectionProvider.java
@@ -14,15 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.ignite.ci;
-
-import org.apache.ignite.ci.user.ICredentialsProv;
+package org.apache.ignite.ci.github;
 
 import javax.annotation.Nullable;
+import org.apache.ignite.ci.user.ICredentialsProv;
 
-/**
- * Provides instance to server with appropriate credentials, may cache 
instances to avoid odd server instances.
- */
-public interface ITcServerProvider {
-    IAnalyticsEnabledTeamcity server(String srvId, @Nullable ICredentialsProv 
prov);
+public interface IGitHubConnectionProvider {
+    /**
+     * @param srvId Server id.
+     * @param prov Prov.
+     */
+    public IGitHubConnection server(String srvId, @Nullable ICredentialsProv 
prov);
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuild.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/visa/TcBotTriggerAndSignOffService.java
similarity index 51%
copy from 
ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuild.java
copy to 
ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/visa/TcBotTriggerAndSignOffService.java
index 83e7911..9c620a7 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuild.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/visa/TcBotTriggerAndSignOffService.java
@@ -15,136 +15,81 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.ci.web.rest;
+package org.apache.ignite.ci.visa;
 
 import com.google.common.base.Strings;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Collectors;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
+import com.google.inject.Injector;
+import com.google.inject.Provider;
+import javax.inject.Inject;
 import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
 import org.apache.ignite.ci.ITcHelper;
+import org.apache.ignite.ci.ITcServerProvider;
 import org.apache.ignite.ci.ITeamcity;
-import org.apache.ignite.ci.conf.ServerIntegrationLinks;
+import org.apache.ignite.ci.github.IGitHubConnection;
+import org.apache.ignite.ci.github.IGitHubConnectionProvider;
 import org.apache.ignite.ci.github.PullRequest;
+import org.apache.ignite.ci.jira.IJiraIntegration;
 import org.apache.ignite.ci.observer.BuildObserver;
 import org.apache.ignite.ci.tcmodel.result.Build;
 import org.apache.ignite.ci.user.ICredentialsProv;
-import org.apache.ignite.ci.web.CtxListener;
-import org.apache.ignite.ci.web.rest.exception.ServiceUnauthorizedException;
 import org.apache.ignite.ci.web.model.SimpleResult;
 import org.apache.ignite.internal.util.typedef.F;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-@Path("build")
-@Produces(MediaType.APPLICATION_JSON)
-public class TriggerBuild {
-    @Context
-    private ServletContext context;
-
-    @Context
-    private HttpServletRequest req;
-
-    @GET
-    @Path("trigger")
-    public SimpleResult triggerBuild(
-        @Nullable @QueryParam("serverId") String srvId,
-        @Nullable @QueryParam("branchName") String branchForTc,
-        @Nullable @QueryParam("suiteId") String suiteId,
-        @Nullable @QueryParam("top") Boolean top,
-        @Nullable @QueryParam("observe") Boolean observe,
-        @Nullable @QueryParam("ticketId") String ticketId
-    ) {
-        String jiraRes = "";
-        final ICredentialsProv prov = ICredentialsProv.get(req);
+/**
+ * Provides method for TC Bot Visa obtaining
+ */
+public class TcBotTriggerAndSignOffService {
 
-        if (!prov.hasAccess(srvId))
-            throw ServiceUnauthorizedException.noCreds(srvId);
+    @Inject Provider<BuildObserver> buildObserverProvider;
 
-        ITcHelper helper = CtxListener.getTcHelper(context);
+    @Inject IGitHubConnectionProvider gitHubConnectionProvider;
 
-        final ITeamcity teamcity = helper.server(srvId, prov);
+    @Inject ITcServerProvider tcServerProvider;
 
-        Build build = teamcity.triggerBuild(suiteId, branchForTc, false, top 
!= null && top);
-
-        if (observe != null && observe)
-            jiraRes = observeJira(srvId, branchForTc, ticketId, teamcity, 
build, prov);
+    @Inject IJiraIntegration jiraIntegration;
 
-        return new SimpleResult("Tests started." + (!jiraRes.isEmpty() ? 
"<br>" + jiraRes : ""));
-    }
+    /**
+     * @param pr Pull Request.
+     * @return JIRA ticket number.
+     */
+    @NotNull public static String getTicketId(PullRequest pr) {
+        String ticketId = "";
 
-    @GET
-    @Path("commentJira")
-    public SimpleResult commentJira(
-        @Nullable @QueryParam("serverId") String srvId,
-        @Nullable @QueryParam("branchName") String branchForTc,
-        @Nullable @QueryParam("suiteId") String suiteId,
-        @Nullable @QueryParam("ticketId") String ticketId
-    ) {
-        try {
-            return commentJiraEx(srvId, branchForTc, suiteId, ticketId);
-        } catch (Exception e) {
-            e.printStackTrace();
+        if (pr.getTitle().startsWith("IGNITE-")) {
+            int beginIdx = 7;
+            int endIdx = 7;
 
-            //todo better exception handling at jersey level
+            while (endIdx < pr.getTitle().length() && 
Character.isDigit(pr.getTitle().charAt(endIdx)))
+                endIdx++;
 
-            throw e;
+            ticketId = pr.getTitle().substring(beginIdx, endIdx);
         }
-    }
 
-    @NotNull
-    public SimpleResult commentJiraEx(
-        @QueryParam("serverId") @Nullable String srvId,
-        @QueryParam("branchName") @Nullable String branchForTc,
-        @QueryParam("suiteId") @Nullable String suiteId,
-        @QueryParam("ticketId") @Nullable String ticketId
-    ) {
-        final ICredentialsProv prov = ICredentialsProv.get(req);
-
-        if (!prov.hasAccess(srvId))
-            throw ServiceUnauthorizedException.noCreds(srvId);
+        return ticketId;
+    }
 
-        ITcHelper helper = CtxListener.getTcHelper(context);
+    @NotNull public String triggerBuildAndObserve(
+        @Nullable String srvId,
+        @Nullable String branchForTc,
+        @Nullable String suiteId,
+        @Nullable Boolean top,
+        @Nullable Boolean observe,
+        @Nullable String ticketId,
+        ICredentialsProv prov,
+        Injector injector) {
         String jiraRes = "";
+        ITcHelper helper = injector.getInstance(ITcHelper.class);
 
         final ITeamcity teamcity = helper.server(srvId, prov);
 
-        if (Strings.isNullOrEmpty(ticketId)) {
-            try {
-                PullRequest pr = teamcity.getPullRequest(branchForTc);
-
-                ticketId = getTicketId(pr);
-
-                if (ticketId.isEmpty()) {
-                    jiraRes = "JIRA ticket can't be commented - " +
-                        "PR title \"" + pr.getTitle() + "\" should starts with 
\"IGNITE-XXXX\"." +
-                        " Please, rename PR according to the" +
-                        " <a 
href='https://cwiki.apache.org/confluence/display/IGNITE/How+to+Contribute"; +
-                        
"#HowtoContribute-1.CreateGitHubpull-request'>contributing guide</a>" +
-                        " or enter ticket id in the form.";
-                }
-            }
-            catch (RuntimeException e) {
-                jiraRes = "Exception happened when server tried to get ticket 
ID from Pull Request - " + e.getMessage();
-            }
-        }
+        Build build = teamcity.triggerBuild(suiteId, branchForTc, false, top 
!= null && top);
 
-        if (!Strings.isNullOrEmpty(ticketId)) {
-            jiraRes = helper.notifyJira(srvId, prov, suiteId, branchForTc, 
"ignite-" + ticketId);
+        if (observe != null && observe)
+            jiraRes = observeJira(srvId, branchForTc, ticketId, teamcity, 
build, prov);
 
-            return new SimpleResult(jiraRes);
-        }
-        else
-            return new SimpleResult("JIRA wasn't commented." + 
(!jiraRes.isEmpty() ? "<br>" + jiraRes : ""));
+        return jiraRes;
     }
 
     /**
@@ -166,7 +111,9 @@ public class TriggerBuild {
     ) {
         if (F.isEmpty(ticketId)) {
             try {
-                PullRequest pr = teamcity.getPullRequest(branchForTc);
+                IGitHubConnection gitHubConnection = 
gitHubConnectionProvider.server(srvId, prov);
+
+                PullRequest pr = gitHubConnection.getPullRequest(branchForTc);
 
                 ticketId = getTicketId(pr);
 
@@ -185,77 +132,52 @@ public class TriggerBuild {
             }
         }
 
-        BuildObserver observer = 
CtxListener.getInjector(context).getInstance(BuildObserver.class);
-
-        observer.observe(build, srvId, prov, "ignite-" + ticketId);
+        buildObserverProvider.get().observe(build, srvId, prov, "ignite-" + 
ticketId);
 
         return "JIRA ticket IGNITE-" + ticketId + " will be notified after the 
tests are completed.";
     }
 
-    /**
-     * @param pr Pull Request.
-     * @return JIRA ticket number.
-     */
-    @NotNull private String getTicketId(PullRequest pr) {
-        String ticketId = "";
-
-        if (pr.getTitle().startsWith("IGNITE-")) {
-            int beginIdx = 7;
-            int endIdx = 7;
-
-            while (endIdx < pr.getTitle().length() && 
Character.isDigit(pr.getTitle().charAt(endIdx)))
-                endIdx++;
-
-            ticketId = pr.getTitle().substring(beginIdx, endIdx);
-        }
-
-        return ticketId;
-    }
-
-    @GET
-    @Path("triggerBuilds")
-    public SimpleResult triggerBuilds(
-        @Nullable @QueryParam("serverId") String serverId,
-        @Nullable @QueryParam("branchName") String branchName,
-        @NotNull @QueryParam("suiteIdList") String suiteIdList,
-        @Nullable @QueryParam("top") Boolean top) {
+    @NotNull
+    public SimpleResult commentJiraEx(
+        @QueryParam("serverId") @Nullable String srvId,
+        @QueryParam("branchName") @Nullable String branchForTc,
+        @QueryParam("suiteId") @Nullable String suiteId,
+        @QueryParam("ticketId") @Nullable String ticketId,
+        ICredentialsProv prov) {
 
-        final ICredentialsProv prov = ICredentialsProv.get(req);
 
-        if (!prov.hasAccess(serverId))
-            throw ServiceUnauthorizedException.noCreds(serverId);
+        String jiraRes = "";
+        final ITeamcity teamcity =  tcServerProvider.server(srvId, prov);
 
-        List<String> strings = Arrays.asList(suiteIdList.split(","));
-        if (strings.isEmpty())
-            return new SimpleResult("Error: nothing to run");
+        if (Strings.isNullOrEmpty(ticketId)) {
+            try {
+                IGitHubConnection gitHubConnection = 
gitHubConnectionProvider.server(srvId, prov);
+                PullRequest pr = gitHubConnection.getPullRequest(branchForTc);
 
-        final ITeamcity helper = 
CtxListener.getTcHelper(context).server(serverId, prov);
+                ticketId = TcBotTriggerAndSignOffService.getTicketId(pr);
 
-        boolean queueToTop = top != null && top;
+                if (ticketId.isEmpty()) {
+                    jiraRes = "JIRA ticket can't be commented - " +
+                        "PR title \"" + pr.getTitle() + "\" should starts with 
\"IGNITE-XXXX\"." +
+                        " Please, rename PR according to the" +
+                        " <a 
href='https://cwiki.apache.org/confluence/display/IGNITE/How+to+Contribute"; +
+                        
"#HowtoContribute-1.CreateGitHubpull-request'>contributing guide</a>" +
+                        " or enter ticket id in the form.";
+                }
+            }
+            catch (RuntimeException e) {
+                jiraRes = "Exception happened when server tried to get ticket 
ID from Pull Request - " + e.getMessage();
+            }
+        }
 
-        for (String suiteId : strings) {
-            System.out.println("Triggering [ " + suiteId + "," + branchName + 
"," + "top=" + queueToTop + "]");
+        if (!Strings.isNullOrEmpty(ticketId)) {
+            jiraRes = jiraIntegration.notifyJira(srvId, prov, suiteId, 
branchForTc, "ignite-" + ticketId);
 
-            helper.triggerBuild(suiteId, branchName, false, queueToTop);
+            return new SimpleResult(jiraRes);
         }
-
-        return new SimpleResult("OK");
+        else
+            return new SimpleResult("JIRA wasn't commented." + 
(!jiraRes.isEmpty() ? "<br>" + jiraRes : ""));
     }
 
-    @GET
-    @Path("integrationUrls")
-    public Set<ServerIntegrationLinks> getIntegrationUrls(@NotNull 
@QueryParam("serverIds") String srvIds) {
-        final ICredentialsProv prov = ICredentialsProv.get(req);
-
-        String[] srvIds0 = srvIds.split(",");
 
-        return Arrays.stream(srvIds0).map(srvId -> {
-            if (!prov.hasAccess(srvId))
-                return null;
-
-            ITeamcity teamcity = CtxListener.server(srvId, context, req);
-
-            return new ServerIntegrationLinks(srvId, teamcity.getGitApiUrl(), 
teamcity.getGitApiUrl());
-        }).filter(Objects::nonNull).collect(Collectors.toSet());
-    }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/UpdateInfo.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/UpdateInfo.java
index 2aeafc6..8ff78c3 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/UpdateInfo.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/UpdateInfo.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.ci.web.model.current;
 
 import org.apache.ignite.ci.IAnalyticsEnabledTeamcity;
+import org.apache.ignite.ci.github.IGitHubConnection;
 
 /**
  * Created by Дмитрий on 19.02.2018
@@ -55,12 +56,14 @@ import org.apache.ignite.ci.IAnalyticsEnabledTeamcity;
 
     /**
      * @param teamcity TeamCity to get info about tokens.
+     * @param gitHubConnection
      */
-    public void setJavaFlags(IAnalyticsEnabledTeamcity teamcity) {
+    public void setJavaFlags(IAnalyticsEnabledTeamcity teamcity,
+        IGitHubConnection gitHubConnection) {
         if (teamcity.isTeamCityTokenAvailable())
             javaFlags |= TEAMCITY_FLAG;
 
-        if (teamcity.isGitTokenAvailable())
+        if (gitHubConnection.isGitTokenAvailable())
             javaFlags |= GITHUB_FLAG;
 
         if (teamcity.isJiraTokenAvailable())
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuild.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuild.java
index 83e7911..49e921f 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuild.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuild.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.ci.web.rest;
 
-import com.google.common.base.Strings;
+import com.google.inject.Injector;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
@@ -34,14 +34,13 @@ import javax.ws.rs.core.MediaType;
 import org.apache.ignite.ci.ITcHelper;
 import org.apache.ignite.ci.ITeamcity;
 import org.apache.ignite.ci.conf.ServerIntegrationLinks;
-import org.apache.ignite.ci.github.PullRequest;
-import org.apache.ignite.ci.observer.BuildObserver;
-import org.apache.ignite.ci.tcmodel.result.Build;
+import org.apache.ignite.ci.github.IGitHubConnection;
+import org.apache.ignite.ci.github.IGitHubConnectionProvider;
 import org.apache.ignite.ci.user.ICredentialsProv;
+import org.apache.ignite.ci.visa.TcBotTriggerAndSignOffService;
 import org.apache.ignite.ci.web.CtxListener;
 import org.apache.ignite.ci.web.rest.exception.ServiceUnauthorizedException;
 import org.apache.ignite.ci.web.model.SimpleResult;
-import org.apache.ignite.internal.util.typedef.F;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -64,24 +63,21 @@ public class TriggerBuild {
         @Nullable @QueryParam("observe") Boolean observe,
         @Nullable @QueryParam("ticketId") String ticketId
     ) {
-        String jiraRes = "";
+
         final ICredentialsProv prov = ICredentialsProv.get(req);
 
         if (!prov.hasAccess(srvId))
             throw ServiceUnauthorizedException.noCreds(srvId);
 
-        ITcHelper helper = CtxListener.getTcHelper(context);
-
-        final ITeamcity teamcity = helper.server(srvId, prov);
+        Injector injector = CtxListener.getInjector(context);
+        TcBotTriggerAndSignOffService triggerAndSignOffSvc = 
injector.getInstance(TcBotTriggerAndSignOffService.class);
 
-        Build build = teamcity.triggerBuild(suiteId, branchForTc, false, top 
!= null && top);
-
-        if (observe != null && observe)
-            jiraRes = observeJira(srvId, branchForTc, ticketId, teamcity, 
build, prov);
+        String jiraRes = triggerAndSignOffSvc. triggerBuildAndObserve(srvId, 
branchForTc, suiteId, top, observe, ticketId, prov, injector);
 
         return new SimpleResult("Tests started." + (!jiraRes.isEmpty() ? 
"<br>" + jiraRes : ""));
     }
 
+
     @GET
     @Path("commentJira")
     public SimpleResult commentJira(
@@ -90,126 +86,16 @@ public class TriggerBuild {
         @Nullable @QueryParam("suiteId") String suiteId,
         @Nullable @QueryParam("ticketId") String ticketId
     ) {
-        try {
-            return commentJiraEx(srvId, branchForTc, suiteId, ticketId);
-        } catch (Exception e) {
-            e.printStackTrace();
-
-            //todo better exception handling at jersey level
-
-            throw e;
-        }
-    }
-
-    @NotNull
-    public SimpleResult commentJiraEx(
-        @QueryParam("serverId") @Nullable String srvId,
-        @QueryParam("branchName") @Nullable String branchForTc,
-        @QueryParam("suiteId") @Nullable String suiteId,
-        @QueryParam("ticketId") @Nullable String ticketId
-    ) {
         final ICredentialsProv prov = ICredentialsProv.get(req);
 
         if (!prov.hasAccess(srvId))
             throw ServiceUnauthorizedException.noCreds(srvId);
 
-        ITcHelper helper = CtxListener.getTcHelper(context);
-        String jiraRes = "";
-
-        final ITeamcity teamcity = helper.server(srvId, prov);
-
-        if (Strings.isNullOrEmpty(ticketId)) {
-            try {
-                PullRequest pr = teamcity.getPullRequest(branchForTc);
-
-                ticketId = getTicketId(pr);
-
-                if (ticketId.isEmpty()) {
-                    jiraRes = "JIRA ticket can't be commented - " +
-                        "PR title \"" + pr.getTitle() + "\" should starts with 
\"IGNITE-XXXX\"." +
-                        " Please, rename PR according to the" +
-                        " <a 
href='https://cwiki.apache.org/confluence/display/IGNITE/How+to+Contribute"; +
-                        
"#HowtoContribute-1.CreateGitHubpull-request'>contributing guide</a>" +
-                        " or enter ticket id in the form.";
-                }
-            }
-            catch (RuntimeException e) {
-                jiraRes = "Exception happened when server tried to get ticket 
ID from Pull Request - " + e.getMessage();
-            }
-        }
-
-        if (!Strings.isNullOrEmpty(ticketId)) {
-            jiraRes = helper.notifyJira(srvId, prov, suiteId, branchForTc, 
"ignite-" + ticketId);
-
-            return new SimpleResult(jiraRes);
-        }
-        else
-            return new SimpleResult("JIRA wasn't commented." + 
(!jiraRes.isEmpty() ? "<br>" + jiraRes : ""));
-    }
-
-    /**
-     * @param srvId Server id.
-     * @param branchForTc Branch for TeamCity.
-     * @param ticketId JIRA ticket number.
-     * @param teamcity TeamCity.
-     * @param build Build.
-     * @param prov Credentials.
-     * @return Message with result.
-     */
-    private String observeJira(
-        String srvId,
-        String branchForTc,
-        @Nullable String ticketId,
-        ITeamcity teamcity,
-        Build build,
-        ICredentialsProv prov
-    ) {
-        if (F.isEmpty(ticketId)) {
-            try {
-                PullRequest pr = teamcity.getPullRequest(branchForTc);
-
-                ticketId = getTicketId(pr);
-
-                if (ticketId.isEmpty()) {
-                    return "JIRA ticket will not be notified after the tests 
are completed - " +
-                        "PR title \"" + pr.getTitle() + "\" should starts with 
\"IGNITE-XXXX\"." +
-                        " Please, rename PR according to the" +
-                        " <a 
href='https://cwiki.apache.org/confluence/display/IGNITE/How+to+Contribute"; +
-                        
"#HowtoContribute-1.CreateGitHubpull-request'>contributing guide</a>.";
-                }
-            }
-            catch (Exception e) {
-                return "JIRA ticket will not be notified after the tests are 
completed - " +
-                    "exception happened when server tried to get ticket ID 
from Pull Request [errMsg=" +
-                    e.getMessage() + ']';
-            }
-        }
-
-        BuildObserver observer = 
CtxListener.getInjector(context).getInstance(BuildObserver.class);
-
-        observer.observe(build, srvId, prov, "ignite-" + ticketId);
-
-        return "JIRA ticket IGNITE-" + ticketId + " will be notified after the 
tests are completed.";
-    }
-
-    /**
-     * @param pr Pull Request.
-     * @return JIRA ticket number.
-     */
-    @NotNull private String getTicketId(PullRequest pr) {
-        String ticketId = "";
+        Injector injector = CtxListener.getInjector(context);
 
-        if (pr.getTitle().startsWith("IGNITE-")) {
-            int beginIdx = 7;
-            int endIdx = 7;
+        TcBotTriggerAndSignOffService signOffSvc = 
injector.getInstance(TcBotTriggerAndSignOffService.class);
 
-            while (endIdx < pr.getTitle().length() && 
Character.isDigit(pr.getTitle().charAt(endIdx)))
-                endIdx++;
-
-            ticketId = pr.getTitle().substring(beginIdx, endIdx);
-        }
-
-        return ticketId;
+        return signOffSvc.commentJiraEx(srvId, branchForTc, suiteId, ticketId, 
prov);
     }
 
     @GET
@@ -253,9 +139,15 @@ public class TriggerBuild {
             if (!prov.hasAccess(srvId))
                 return null;
 
-            ITeamcity teamcity = CtxListener.server(srvId, context, req);
+            Injector injector = CtxListener.getInjector(context);
+
+            ITcHelper tcHelper = injector.getInstance(ITcHelper.class);
+            final ICredentialsProv creds = ICredentialsProv.get(req);
+            ITeamcity teamcity = tcHelper.server(srvId, creds);
+
+            IGitHubConnection gh = 
injector.getInstance(IGitHubConnectionProvider.class).server(srvId, prov);
 
-            return new ServerIntegrationLinks(srvId, teamcity.getGitApiUrl(), 
teamcity.getGitApiUrl());
+            return new ServerIntegrationLinks(srvId, gh.gitApiUrl(), 
teamcity.getJiraApiUrl());
         }).filter(Objects::nonNull).collect(Collectors.toSet());
     }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/pr/GetPrTestFailures.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/pr/GetPrTestFailures.java
index e113b6a..152d8d5 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/pr/GetPrTestFailures.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/pr/GetPrTestFailures.java
@@ -21,8 +21,9 @@ import javax.ws.rs.FormParam;
 import javax.ws.rs.POST;
 
 import com.google.inject.Injector;
-import org.apache.ignite.ci.*;
 import org.apache.ignite.ci.chain.PrChainsProcessor;
+import org.apache.ignite.ci.github.IGitHubConnection;
+import org.apache.ignite.ci.github.IGitHubConnectionProvider;
 import org.apache.ignite.ci.github.PullRequest;
 import org.apache.ignite.ci.user.ICredentialsProv;
 import org.apache.ignite.ci.web.BackgroundUpdater;
@@ -132,12 +133,14 @@ public class GetPrTestFailures {
         if (!branchForTc.startsWith("pull/"))
             return "Given branch is not a pull request. Notify works only for 
pull requests.";
 
-        IAnalyticsEnabledTeamcity teamcity = CtxListener.server(srvId, ctx, 
req);
+        final Injector injector = CtxListener.getInjector(ctx);
+        final ICredentialsProv creds = ICredentialsProv.get(req);
+        final IGitHubConnection srv = 
injector.getInstance(IGitHubConnectionProvider.class).server(srvId, creds);
 
         PullRequest pr;
 
         try {
-            pr = teamcity.getPullRequest(branchForTc);
+            pr = srv.getPullRequest(branchForTc);
         }
         catch (RuntimeException e) {
             return "Exception happened - " + e.getMessage();
@@ -145,7 +148,7 @@ public class GetPrTestFailures {
 
         String statusesUrl = pr.getStatusesUrl();
 
-        teamcity.notifyGit(statusesUrl, msg);
+        srv.notifyGit(statusesUrl, msg);
 
 
         return "Git was notified.";

Reply via email to