You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ignite.apache.org by GitBox <gi...@apache.org> on 2018/09/12 13:05:45 UTC

[GitHub] asfgit closed pull request #5: IGNITE-9377

asfgit closed pull request #5: IGNITE-9377
URL: https://github.com/apache/ignite-teamcity-bot/pull/5
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

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 3f2e9b8..b3b51c7 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
@@ -48,6 +48,7 @@
     @Deprecated
     private static final String PASSWORD = "password";
     public static final String ENCODED_PASSWORD = "encoded_password";
+    public static final String GITHUB_AUTH_TOKEN = "github.auth_token";
     public static final String SLACK_AUTH_TOKEN = "slack.auth_token";
     public static final String SLACK_CHANNEL = "slack.channel";
     public static final String LOGS = "logs";
@@ -117,19 +118,45 @@ public static File resolveWorkDir() {
         return ensureDirExist(workDir);
     }
 
+    /**
+     * Extract GitHub authorization token from properties.
+     *
+     * @param props Properties, where token is placed.
+     * @return Null or decoded auth token for Github.
+     */
+    @Nullable static String prepareGithubHttpAuthToken(Properties props) {
+        String pwd = props.getProperty(GITHUB_AUTH_TOKEN);
+
+        if (isNullOrEmpty(pwd))
+            return null;
+
+        pwd = PasswordEncoder.decode(pwd);
+
+        return pwd;
+    }
+
+    /**
+     * Extract TeamCity authorization token from properties.
+     *
+     * @param props Properties, where token is placed.
+     * @param configName Configuration name.
+     * @return Null or decoded auth token for Github.
+     */
     @Nullable static String prepareBasicHttpAuthToken(Properties props, String configName) {
         final String user = getMandatoryProperty(props, USERNAME, configName);
         String pwd = props.getProperty(PASSWORD);
         boolean filled = !isNullOrEmpty(pwd);
-        if(!filled) {
+
+        if (!filled) {
             String enc = props.getProperty(ENCODED_PASSWORD);
+
             if(!isNullOrEmpty(enc)) {
                 pwd = PasswordEncoder.decode(enc);
                 filled = true;
             }
         }
 
-        if(!filled)
+        if (!filled)
             return null;
 
         return Base64Util.encodeUtf8String(user + ":" + pwd);
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 d9d8d1d..6fa8e63 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
@@ -18,6 +18,7 @@
 package org.apache.ignite.ci;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutorService;
@@ -26,6 +27,7 @@
 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.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;
@@ -240,8 +242,41 @@ default SingleBuildRunCtx loadTestsAndProblems(@Nonnull Build build, @Deprecated
      */
     void triggerBuild(String id, String name, boolean cleanRebuild, boolean queueAtTop);
 
+    /**
+     * @return {@code True} if TeamCity authorization token is available.
+     */
+    boolean isTeamCityTokenAvailable();
+
+    /**
+     * @param token TeamCity authorization token.
+     */
     void setAuthToken(String token);
 
+    /**
+     * @return {@code True} if GitHub authorization token is available.
+     */
+    boolean isGitTokenAvailable();
+
+    /**
+     * @param token GitHub authorization token.
+     */
+    void setGitToken(String token);
+
+    /**
+     * 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);
+
     default void setAuthData(String user, String password) {
         setAuthToken(
                 Base64Util.encodeUtf8String(user + ":" + password));
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 e89e2f2..16e3a22 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
@@ -52,6 +52,7 @@
 import org.apache.ignite.ci.analysis.TestInBranch;
 import org.apache.ignite.ci.db.DbMigrations;
 import org.apache.ignite.ci.db.TcHelperDb;
+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.ChangesList;
@@ -822,11 +823,36 @@ public void setExecutor(ExecutorService executor) {
         teamcity.triggerBuild(id, name, cleanRebuild, queueAtTop);
     }
 
-    @Override
-    public void setAuthToken(String token) {
+    /** {@inheritDoc} */
+    @Override public boolean isTeamCityTokenAvailable() {
+        return teamcity.isTeamCityTokenAvailable();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setAuthToken(String token) {
         teamcity.setAuthToken(token);
     }
 
+    /** {@inheritDoc} */
+    @Override public boolean isGitTokenAvailable() {
+        return teamcity.isGitTokenAvailable();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setGitToken(String token) {
+        teamcity.setGitToken(token);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean notifyGit(String url, String body) {
+        return teamcity.notifyGit(url, body);
+    }
+
+    /** {@inheritDoc} */
+    @Override public PullRequest getPullRequest(String branch) {
+        return teamcity.getPullRequest(branch);
+    }
+
     /** {@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/IgniteTeamcityHelper.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityHelper.java
index d3421b7..cf7ec6a 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityHelper.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityHelper.java
@@ -21,6 +21,7 @@
 import com.google.common.base.Stopwatch;
 import com.google.common.base.Throwables;
 import com.google.common.util.concurrent.MoreExecutors;
+import com.google.gson.Gson;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -48,6 +49,7 @@
 import org.apache.ignite.ci.analysis.LogCheckTask;
 import org.apache.ignite.ci.analysis.MultBuildRunCtx;
 import org.apache.ignite.ci.analysis.SingleBuildRunCtx;
+import org.apache.ignite.ci.github.PullRequest;
 import org.apache.ignite.ci.logs.BuildLogStreamChecker;
 import org.apache.ignite.ci.logs.LogsAnalyzer;
 import org.apache.ignite.ci.logs.handlers.TestLogHandler;
@@ -87,6 +89,7 @@
  *
  * See more info about API
  * https://confluence.jetbrains.com/display/TCD10/REST+API
+ * https://developer.github.com/v3/
  */
 public class IgniteTeamcityHelper implements ITeamcity {
     /** Logger. */
@@ -96,7 +99,13 @@
     private final File logsDir;
     /** Normalized Host address, ends with '/'. */
     private final String host;
+
+    /** TeamCity authorization token. */
     private String basicAuthTok;
+
+    /** GitHub authorization token. */
+    private String gitAuthTok;
+
     private final String configName; //main properties file name
     private final String tcName;
 
@@ -120,6 +129,8 @@ public IgniteTeamcityHelper(@Nullable String tcName) {
             e.printStackTrace();
         }
 
+        setGitToken(HelperConfig.prepareGithubHttpAuthToken(props));
+
         final File logsDirFile = HelperConfig.resolveLogs(workDir, props);
 
         logsDir = ensureDirExist(logsDirFile);
@@ -127,10 +138,66 @@ public IgniteTeamcityHelper(@Nullable String tcName) {
         this.executor =  MoreExecutors.directExecutor();
     }
 
-    public void setAuthToken(String token) {
+    /** {@inheritDoc} */
+    @Override public boolean isTeamCityTokenAvailable() {
+        return basicAuthTok != null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setAuthToken(String token) {
         basicAuthTok = token;
     }
 
+    /** {@inheritDoc} */
+    @Override public boolean isGitTokenAvailable() {
+        return gitAuthTok != null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setGitToken(String token) {
+        gitAuthTok = token;
+    }
+
+    /** {@inheritDoc} */
+    @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 PullRequest getPullRequest(String branch) {
+        String id = null;
+
+        for (int i = 5; i < branch.length(); i++) {
+            char c = branch.charAt(i);
+
+            if (!Character.isDigit(c)) {
+                id = branch.substring(5, i);
+
+                break;
+            }
+        }
+
+        String pr = "https://api.github.com/repos/" + serverId() + "/ignite/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} */
     @Override public List<Agent> agents(boolean connected, boolean authorized) {
         String url = "app/rest/agents?locator=connected:" + connected + ",authorized:" + authorized;
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/PullRequest.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/PullRequest.java
new file mode 100644
index 0000000..d381d12
--- /dev/null
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/PullRequest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.annotations.SerializedName;
+
+/**
+ *
+ */
+public class PullRequest {
+    /** Pull Request number. You can see it at {@code apache/ignite/pull/"number"}. */
+    @SerializedName("number") private int num;
+
+    /** Pull Request state. */
+    private String state;
+
+    /** Pull Request title. */
+    private String title;
+
+    /** Pull Request url to get statuses. */
+    @SerializedName("statuses_url") private String statusesUrl;
+
+    /**
+     * @return Pull Request number.
+     */
+    public int getNumber() {
+        return num;
+    }
+
+    /**
+     * @return Pull Request state.
+     */
+    public String getState() {
+        return state;
+    }
+
+    /**
+     * @return Pull Request title.
+     */
+    public String getTitle() {
+        return title;
+    }
+
+    /**
+     * @return Url to get PR statuses.
+     */
+    public String getStatusesUrl() {
+        return statusesUrl;
+    }
+}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/HttpUtil.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/HttpUtil.java
index af82375..ee20902 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/HttpUtil.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/HttpUtil.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.ci.util;
 
 import com.google.common.base.Stopwatch;
-import org.apache.ignite.ci.BuildChainProcessor;
+import org.apache.ignite.ci.conf.PasswordEncoder;
 import org.apache.ignite.ci.web.rest.login.ServiceUnauthorizedException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -56,6 +56,14 @@ private static String readIsToString(InputStream inputStream) throws IOException
         return response.toString();
     }
 
+    /**
+     * Send GET request to the TeamCity url.
+     *
+     * @param basicAuthToken Authorization token.
+     * @param url URL.
+     * @return Input stream from connection.
+     * @throws IOException If failed.
+     */
     public static InputStream sendGetWithBasicAuth(String basicAuthToken, String url) throws IOException {
         final Stopwatch started = Stopwatch.createStarted();
         URL obj = new URL(url);
@@ -66,12 +74,34 @@ public static InputStream sendGetWithBasicAuth(String basicAuthToken, String url
         con.setRequestProperty("Keep-Alive", "header");
         con.setRequestProperty("accept-charset", StandardCharsets.UTF_8.toString());
 
-        int resCode = con.getResponseCode();
+        logger.info(Thread.currentThread().getName() + ": Required: " + started.elapsed(TimeUnit.MILLISECONDS)
+            + "ms : Sending 'GET' request to : " + url);
+
+        return getInputStream(con);
+    }
+
+    /**
+     * Send GET request to the GitHub url.
+     *
+     * @param githubAuthToken Authorization token.
+     * @param url URL.
+     * @return Input stream from connection.
+     * @throws IOException If failed.
+     */
+    public static InputStream sendGetToGit(String githubAuthToken, String url) throws IOException {
+        Stopwatch started = Stopwatch.createStarted();
+        URL obj = new URL(url);
+        HttpURLConnection con = (HttpURLConnection)obj.openConnection();
+
+        con.setRequestProperty("accept-charset", StandardCharsets.UTF_8.toString());
+        con.setRequestProperty("Authorization", "token " + githubAuthToken);
+        con.setRequestProperty("Connection", "Keep-Alive");
+        con.setRequestProperty("Keep-Alive", "header");
 
         logger.info(Thread.currentThread().getName() + ": Required: " + started.elapsed(TimeUnit.MILLISECONDS)
             + "ms : Sending 'GET' request to : " + url);
 
-        return getInputStream(url, con, resCode);
+        return getInputStream(con);
     }
 
     public static void sendGetCopyToFile(String tok, String url, File file) throws IOException {
@@ -105,24 +135,65 @@ private static InputStream sendPostWithBasicAuth(String tok, String url,
             writer.write(body); // Write POST query string (if any needed).
         }
 
-        int resCode = con.getResponseCode();
-
         logger.info("\nSending 'POST' request to URL : " + url + "\n" + body);
 
-        return getInputStream(url, con, resCode);
+        return getInputStream(con);
 
     }
 
-    private static InputStream getInputStream(String url, HttpURLConnection con, int resCode) throws IOException {
-        if (resCode == 200) {
+    /**
+     * Get input stream for successful connection. Throws exception if connection response wasn't successful.
+     *
+     * @param con Http connection.
+     * @return Input stream from connection.
+     * @throws IOException If failed.
+     */
+    private static InputStream getInputStream(HttpURLConnection con) throws IOException {
+        int resCode = con.getResponseCode();
+
+        // Successful responses (with code 200+).
+        if (resCode / 100 == 2)
             return con.getInputStream();
-        }
 
-        if (resCode == 401) {
-            throw new ServiceUnauthorizedException("Service " + url + " returned forbidden error");
-        }
+        if (resCode == 401)
+            throw new ServiceUnauthorizedException("Service " + con.getURL() + " returned forbidden error.");
 
         throw new IllegalStateException("Invalid Response Code : " + resCode + ":\n"
-                + readIsToString(con.getInputStream()));
+                + readIsToString(con.getErrorStream()));
+    }
+
+    /**
+     * Send POST request to the GitHub url.
+     *
+     * @param githubAuthToken Authorization token.
+     * @param url URL.
+     * @param body Request POST params.
+     * @return Response body from given url.
+     * @throws IOException If failed.
+     */
+    public static String sendPostAsStringToGit(String githubAuthToken, String url, String body) throws IOException {
+        URL obj = new URL(url);
+        HttpURLConnection con = (HttpURLConnection)obj.openConnection();
+        Charset charset = StandardCharsets.UTF_8;
+
+        con.setRequestProperty("accept-charset", charset.toString());
+        con.setRequestProperty("Authorization", "token " + githubAuthToken);
+        con.setRequestProperty("Connection", "Keep-Alive");
+        con.setRequestProperty("Keep-Alive", "header");
+        con.setRequestProperty("content-type", "application/json");
+
+        con.setRequestMethod("POST");
+
+        con.setDoOutput(true);
+
+        try (OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream(), charset)){
+            writer.write(body); // Write POST query string (if any needed).
+        }
+
+        logger.info("\nSending 'POST' request to URL : " + url + "\n" + body);
+
+        try (InputStream inputStream = getInputStream(con)){
+            return readIsToString(inputStream);
+        }
     }
 }
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 8a20443..50b71f7 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
@@ -17,10 +17,21 @@
 
 package org.apache.ignite.ci.web.model.current;
 
+import org.apache.ignite.ci.IAnalyticsEnabledTeamcity;
+
 /**
  * Created by Дмитрий on 19.02.2018
  */
 @SuppressWarnings("WeakerAccess") public class UpdateInfo {
+    /** TeamCity auth token availability flag. */
+    public static int TEAMCITY_FLAG = 1;
+
+    /** GitHub auth token availability flag. */
+    public static int GITHUB_FLAG = 2;
+
+    /** Flags to use in javascript. */
+    public Integer javaFlags = 0;
+
     /** Update required, set by background updater. */
     public boolean updateRequired = false;
 
@@ -38,4 +49,15 @@ public UpdateInfo copyFrom(UpdateInfo info) {
 
         return this;
     }
+
+    /**
+     * @param teamcity TeamCity to get info about tokens.
+     */
+    public void setJavaFlags(IAnalyticsEnabledTeamcity teamcity) {
+        if (teamcity.isTeamCityTokenAvailable())
+            javaFlags = javaFlags | TEAMCITY_FLAG;
+
+        if (teamcity.isGitTokenAvailable())
+            javaFlags = javaFlags | GITHUB_FLAG;
+    }
 }
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 b530b2e..12344b4 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
@@ -17,10 +17,13 @@
 
 package org.apache.ignite.ci.web.rest.pr;
 
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
 import org.apache.ignite.ci.*;
 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.github.PullRequest;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.user.ICredentialsProv;
 import org.apache.ignite.ci.web.BackgroundUpdater;
@@ -108,6 +111,8 @@ public TestFailuresSummary getPrFailures(
 
         //using here non persistent TC allows to skip update statistic
         try (IAnalyticsEnabledTeamcity teamcity = tcHelper.server(srvId, creds)) {
+            res.setJavaFlags(teamcity);
+
             LatestRebuildMode rebuild;
             if (FullQueryParams.HISTORY.equals(action))
                 rebuild = LatestRebuildMode.ALL;
@@ -167,4 +172,29 @@ else if (FullQueryParams.CHAIN.equals(action))
 
         return res;
     }
+
+    @POST
+    @Path("notifyGit")
+    public String getNotifyGit(
+        @Nullable @QueryParam("serverId") String srvId,
+        @Nonnull @QueryParam("suiteId") String suiteId,
+        @Nonnull @QueryParam("branchForTc") String branchForTc,
+        @Nonnull @QueryParam("action") String action,
+        @Nullable @QueryParam("count") Integer count,
+        @Nonnull @FormParam("notifyMsg") String msg) {
+        if (!branchForTc.startsWith("pull/"))
+            return "Given branch is not a pull request. Notify works only for pull requests.";
+
+        ITcHelper tcHelper = CtxListener.getTcHelper(context);
+        final ICredentialsProv creds = ICredentialsProv.get(req);
+
+        try (IAnalyticsEnabledTeamcity teamcity = tcHelper.server(srvId, creds)) {
+            PullRequest pr = teamcity.getPullRequest(branchForTc);
+            String statusesUrl = pr.getStatusesUrl();
+
+            teamcity.notifyGit(statusesUrl, msg);
+        }
+
+        return "Git was notified.";
+    }
 }
diff --git a/ignite-tc-helper-web/src/main/webapp/js/testfails-2.1.js b/ignite-tc-helper-web/src/main/webapp/js/testfails-2.1.js
index 3502592..e8af7d6 100644
--- a/ignite-tc-helper-web/src/main/webapp/js/testfails-2.1.js
+++ b/ignite-tc-helper-web/src/main/webapp/js/testfails-2.1.js
@@ -3,6 +3,9 @@
 //triggerConfirm & triggerDialog element should be provided on page (may be hidden)
 var g_initMoreInfoDone = false;
 
+/** Object used to notify git. See ChainAtServerCurrentStatus Java class. */
+var g_srv_to_notify_git;
+
 //@param results - TestFailuresSummary
 function showChainOnServersResults(result) {
     var minFailRateP = findGetParameter("minFailRate");
@@ -10,14 +13,24 @@ function showChainOnServersResults(result) {
 
     var maxFailRateP = findGetParameter("maxFailRate");
     var maxFailRate = maxFailRateP == null ? 100 : parseFloat(maxFailRateP);
-    return showChainResultsWithSettings(result, new Settings(minFailRate, maxFailRate));
+
+    return showChainResultsWithSettings(result, new Settings(minFailRate, maxFailRate, result.javaFlags));
 }
 
 class Settings {
-    constructor(minFailRate, maxFailRate) {
+    constructor(minFailRate, maxFailRate, javaFlags) {
         this.minFailRate = minFailRate;
         this.maxFailRate = maxFailRate;
+        this.javaFlags = javaFlags;
     }
+
+    isTeamCityAvailable() {
+        return this.javaFlags & 1;
+    };
+
+    isGithubAvailable() {
+        return this.javaFlags & 2
+    };
 }
 
 //@param results - TestFailuresSummary
@@ -67,7 +80,7 @@ function showChainCurrentStatusData(server, settings) {
         altTxt += "duration: " + server.durationPrintable;
 
     res += "<table border='0px'>";
-    res += "<tr bgcolor='#F5F5FF'><td colspan='4'><b><a href='" + server.webToHist + "'>";
+    res += "<tr bgcolor='#F5F5FF'><td colspan='3'><b><a href='" + server.webToHist + "'>";
 
     if (isDefinedAndFilled(server.chainName)) {
         res += server.chainName + " ";
@@ -141,7 +154,13 @@ function showChainCurrentStatusData(server, settings) {
         res += "<div class='content'>" + mInfo + "</div></span>";
     }
 
-    res += "</td></tr>";
+    if (settings.isGithubAvailable()) {
+        g_srv_to_notify_git = server;
+
+        res += "</td><td><button onclick='notifyGit()'>Update PR status</button></td></tr>";
+    }
+    else
+        res += "</td><td>&nbsp;</td></tr>";
 
     res += addBlockersData(server, settings);
 
@@ -218,6 +237,59 @@ function suiteWithCriticalFailuresOnly(suite) {
     return null;
 }
 
+/**
+ * Send POST request to change PR status.
+ *
+ * @returns {string}
+ */
+function notifyGit() {
+    var server = g_srv_to_notify_git;
+    var suites = 0;
+    var tests = 0;
+
+    for (let suite of server.suites) {
+        if (suite.result != "") {
+            suites++;
+
+            continue;
+        }
+
+        for (let testFailure of suite.testFailures) {
+            if (isNewFailedTest(testFailure))
+                tests++;
+        }
+    }
+
+    var state;
+    var desc;
+
+    if (suites == 0 && tests == 0) {
+        state = "success";
+        desc = "No blockers found.";
+    }
+    else {
+        state = "failure";
+        desc = suites + " critical suites, " + tests + " failed tests.";
+    }
+
+    var msg = {
+        state: state,
+        target_url: server.webToHist,
+        description: desc,
+        context: "TeamCity"
+    };
+
+    var notifyGitUrl = "rest/pr/notifyGit"  + parmsForRest();
+
+    $.ajax({
+        url: notifyGitUrl,
+        type: 'POST',
+        data: {notifyMsg: JSON.stringify(msg)},
+        success: function(result) {$("#loadStatus").html(result);},
+        error: showErrInLoadStatus
+    });
+}
+
 function triggerBuild(serverId, suiteId, branchName, top) {
     var queueAtTop = isDefinedAndFilled(top) && top;
     $.ajax({


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services