This is an automated email from the ASF dual-hosted git repository. dpavlov pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ignite-teamcity-bot.git
commit 32d6bf85b00261d7cd9d39144f871fa64343c709 Author: Dmitrii Ryabov <[email protected]> AuthorDate: Wed Sep 12 16:05:06 2018 +0300 IGNITE-9377 Handle print critical failures to the GitHub PR statuses - Fixes #5. Signed-off-by: Dmitriy Pavlov <[email protected]> --- .../java/org/apache/ignite/ci/HelperConfig.java | 31 ++++++- .../main/java/org/apache/ignite/ci/ITeamcity.java | 34 +++++++ .../apache/ignite/ci/IgnitePersistentTeamcity.java | 30 +++++- .../org/apache/ignite/ci/IgniteTeamcityHelper.java | 69 +++++++++++++- .../org/apache/ignite/ci/github/PullRequest.java | 65 +++++++++++++ .../java/org/apache/ignite/ci/util/HttpUtil.java | 102 +++++++++++++++++---- .../ignite/ci/web/model/current/UpdateInfo.java | 22 +++++ .../ignite/ci/web/rest/pr/GetPrTestFailures.java | 30 ++++++ .../src/main/webapp/js/testfails-2.1.js | 80 +++++++++++++++- 9 files changed, 437 insertions(+), 26 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 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 @@ public class HelperConfig { @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 class HelperConfig { 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..7e105c7 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 @@ -26,6 +26,7 @@ import javax.annotation.Nullable; 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 +241,41 @@ public interface ITeamcity extends AutoCloseable { */ 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.SuiteInBranch; 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,12 +823,37 @@ public class IgnitePersistentTeamcity implements IAnalyticsEnabledTeamcity, ITea 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.Preconditions; 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.LogCheckResult; 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 @@ import static org.apache.ignite.ci.HelperConfig.ensureDirExist; * * 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 @@ public class IgniteTeamcityHelper implements ITeamcity { 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 class IgniteTeamcityHelper implements ITeamcity { e.printStackTrace(); } + setGitToken(HelperConfig.prepareGithubHttpAuthToken(props)); + final File logsDirFile = HelperConfig.resolveLogs(workDir, props); logsDir = ensureDirExist(logsDirFile); @@ -127,11 +138,67 @@ public class IgniteTeamcityHelper implements ITeamcity { 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..8234f8a 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,11 +18,6 @@ package org.apache.ignite.ci.util; import com.google.common.base.Stopwatch; -import org.apache.ignite.ci.BuildChainProcessor; -import org.apache.ignite.ci.web.rest.login.ServiceUnauthorizedException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.BufferedReader; import java.io.File; import java.io.IOException; @@ -36,6 +31,9 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.concurrent.TimeUnit; +import org.apache.ignite.ci.web.rest.login.ServiceUnauthorizedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Methods for sending HTTP requests @@ -56,6 +54,14 @@ public class HttpUtil { 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 +72,34 @@ public class HttpUtil { 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 +133,64 @@ public class HttpUtil { writer.write(body); // Write POST query string (if any needed). } + logger.info("\nSending 'POST' request to URL : " + url + "\n" + body); + + return getInputStream(con); + } + + /** + * 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(); - logger.info("\nSending 'POST' request to URL : " + url + "\n" + body); + // Successful responses (with code 200+). + if (resCode / 100 == 2) + return con.getInputStream(); - return getInputStream(url, con, resCode); + if (resCode == 401) + throw new ServiceUnauthorizedException("Service " + con.getURL() + " returned forbidden error."); + throw new IllegalStateException("Invalid Response Code : " + resCode + ":\n" + + readIsToString(con.getErrorStream())); } - private static InputStream getInputStream(String url, HttpURLConnection con, int resCode) throws IOException { - if (resCode == 200) { - return con.getInputStream(); - } + /** + * 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"); - if (resCode == 401) { - throw new ServiceUnauthorizedException("Service " + url + " returned forbidden error"); + con.setRequestMethod("POST"); + + con.setDoOutput(true); + + try (OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream(), charset)){ + writer.write(body); // Write POST query string (if any needed). } - throw new IllegalStateException("Invalid Response Code : " + resCode + ":\n" - + readIsToString(con.getInputStream())); + 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 @@ package org.apache.ignite.ci.web.model.current; 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 class GetPrTestFailures { //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 @@ public class GetPrTestFailures { 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> </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({
