This is an automated email from the ASF dual-hosted git repository.
irakov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite-teamcity-bot.git
The following commit(s) were added to refs/heads/master by this push:
new 81c9280 Highlight newly added tests in TC bot visa (#158)
81c9280 is described below
commit 81c92809ff905e58ab3d05a4ae6a6fbba4fcd9a5
Author: sergeyuttsel <[email protected]>
AuthorDate: Mon Apr 27 20:22:22 2020 +0300
Highlight newly added tests in TC bot visa (#158)
Signed-off-by: Ivan Rakov <[email protected]>
---
build.gradle | 2 +-
.../apache/ignite/ci/tcbot/TcBotWebAppModule.java | 3 +
.../tcbot/visa/TcBotTriggerAndSignOffService.java | 84 +++++++++++++++-
.../src/main/webapp/js/testfails-2.2.js | 49 ++++++++-
.../ci/tcbot/chain/MockBasedTcBotModule.java | 3 +
.../tcbot/engine/chain/TestCompactedMult.java | 10 +-
.../ignite/tcbot/engine/pr/PrChainsProcessor.java | 109 ++++++++++++++++++++-
.../apache/ignite/tcbot/engine/ui/DsChainUi.java | 43 ++++++++
.../tcbot/engine/ui/ShortSuiteNewTestsUi.java | 46 +++++++++
.../apache/ignite/tcbot/engine/ui/ShortTestUi.java | 68 +++++++++++++
.../org/apache/ignite/tcservice/ITeamcityConn.java | 7 ++
.../tcservice/TeamcityServiceConnection.java | 10 ++
12 files changed, 425 insertions(+), 9 deletions(-)
diff --git a/build.gradle b/build.gradle
index 7c1c4b7..2c8ce94 100644
--- a/build.gradle
+++ b/build.gradle
@@ -47,7 +47,7 @@ allprojects {
jettyVer = '9.4.12.v20180830'
// ignVer = '2.7.0'
- ignVer = '2.7.6'
+ ignVer = '2.8.0'
// ignVer = '2.7.0-SNAPSHOT'
guavaVer = '26.0-jre'
diff --git
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/TcBotWebAppModule.java
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/TcBotWebAppModule.java
index c4affe0..969e6b6 100644
---
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/TcBotWebAppModule.java
+++
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/TcBotWebAppModule.java
@@ -44,6 +44,8 @@ import
org.apache.ignite.tcbot.notify.TcBotNotificationsModule;
import org.apache.ignite.tcbot.persistence.TcBotPersistenceModule;
import org.apache.ignite.tcbot.persistence.scheduler.SchedulerModule;
import org.apache.ignite.tcignited.TeamcityIgnitedModule;
+import org.apache.ignite.tcservice.ITeamcityConn;
+import org.apache.ignite.tcservice.TeamcityServiceConnection;
/**
*
@@ -70,6 +72,7 @@ public class TcBotWebAppModule extends AbstractModule {
}
});
+ bind(ITeamcityConn.class).toInstance(new TeamcityServiceConnection());
bind(TcUpdatePool.class).in(new SingletonScope());
bind(IssueDetector.class).in(new SingletonScope());
bind(ObserverTask.class).in(new SingletonScope());
diff --git
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java
index c97fd66..8acb1e1 100644
---
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java
+++
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/TcBotTriggerAndSignOffService.java
@@ -69,7 +69,9 @@ import org.apache.ignite.tcbot.engine.conf.ITcBotConfig;
import org.apache.ignite.tcbot.engine.pr.BranchTicketMatcher;
import org.apache.ignite.tcbot.engine.pr.PrChainsProcessor;
import org.apache.ignite.tcbot.engine.ui.ShortSuiteUi;
+import org.apache.ignite.tcbot.engine.ui.ShortSuiteNewTestsUi;
import org.apache.ignite.tcbot.engine.ui.ShortTestFailureUi;
+import org.apache.ignite.tcbot.engine.ui.ShortTestUi;
import org.apache.ignite.tcbot.persistence.IStringCompactor;
import org.apache.ignite.tcignited.ITeamcityIgnited;
import org.apache.ignite.tcignited.ITeamcityIgnitedProvider;
@@ -828,13 +830,17 @@ public class TcBotTriggerAndSignOffService {
SyncMode.RELOAD_QUEUED,
baseBranch);
+ List<ShortSuiteNewTestsUi> newTestsStatuses =
prChainsProcessor.getNewTestsSuitesStatuses(buildTypeId, build.branchName,
srvCodeOrAlias, prov,
+ SyncMode.RELOAD_QUEUED,
+ baseBranch);
+
if (suitesStatuses == null)
return new Visa("JIRA wasn't commented - no finished builds to
analyze." +
" Check builds availabiliy for branch: " +
build.branchName + "/" + baseBranch);
blockers =
suitesStatuses.stream().mapToInt(ShortSuiteUi::totalBlockers).sum();
- String comment = generateJiraComment(suitesStatuses, build.webUrl,
buildTypeId, tcIgnited, blockers, build.branchName, baseBranch);
+ String comment = generateJiraComment(suitesStatuses,
newTestsStatuses, build.webUrl, buildTypeId, tcIgnited, blockers,
build.branchName, baseBranch);
res = objMapper.readValue(jira.postJiraComment(ticket, comment),
JiraCommentResponse.class);
@@ -861,7 +867,7 @@ public class TcBotTriggerAndSignOffService {
* @param baseBranch TC Base branch used for comment
* @return Comment, which should be sent to the JIRA ticket.
*/
- private String generateJiraComment(List<ShortSuiteUi> suites, String
webUrl, String buildTypeId,
+ private String generateJiraComment(List<ShortSuiteUi> suites,
List<ShortSuiteNewTestsUi> newTestsStatuses, String webUrl, String buildTypeId,
ITeamcityIgnited tcIgnited, int blockers, String branchName, String
baseBranch) {
BuildTypeRefCompacted bt = tcIgnited.getBuildTypeRef(buildTypeId);
@@ -909,6 +915,61 @@ public class TcBotTriggerAndSignOffService {
res.append("\\n");
}
+ StringBuilder newTests = new StringBuilder();
+
+ int newTestsCount = 0;
+
+ int failedNewTestsCount = 0;
+
+ for (ShortSuiteNewTestsUi suite : newTestsStatuses) {
+ newTests.append("{color:#00008b}");
+
+ newTests.append(jiraEscText(suite.name)).append("{color}");
+
+ int totalNewTests = suite.tests.size();
+ newTests.append(" [tests ").append(totalNewTests);
+
+ int cnt = 0;
+
+ newTestsCount += suite.tests().size();
+
+ newTests.append("]\\n");
+
+ for (ShortTestUi test : suite.tests()) {
+ String testColor;
+ if (test.status)
+ testColor = "#013220";
+ else {
+ testColor = "#8b0000";
+ failedNewTestsCount++;
+ }
+
+ newTests.append("* ");
+
+ newTests.append(String.format("{color:%s}", testColor));
+
+ if (test.suiteName != null && test.testName != null)
+ newTests.append(jiraEscText(test.suiteName)).append(":
").append(jiraEscText(test.testName));
+ else
+ newTests.append(jiraEscText(test.name));
+
+ newTests.append(" - ").append(jiraEscText(test.status ?
"PASSED" : "FAILED"));
+
+ newTests.append("{color}");
+
+ newTests.append("\\n");
+
+ cnt++;
+ if (cnt > 10) {
+ newTests.append("... and ").append(totalNewTests -
cnt).append(" tests blockers\\n");
+
+ break;
+ }
+ }
+
+ newTests.append("\\n");
+ }
+
String suiteNameForComment = jiraEscText(suiteNameUsedForVisa);
String branchNameForComment = jiraEscText("Branch: [" + branchName +
"] ");
@@ -928,7 +989,24 @@ public class TcBotTriggerAndSignOffService {
.append("borderStyle=dashed|borderColor=#ccc|titleBGColor=#D6F7C1}{panel}");
}
- res.append("\\n").append("[TeamCity
*").append(suiteNameForComment).append("* Results|").append(webUrl).append(']');
+ if (newTests.length() > 0) {
+ String bgColor;
+ if (failedNewTestsCount > 0)
+ bgColor = "#F7D6C1";
+ else
+ bgColor = "#D6F7C1";
+ String hdrPanel = "{panel:title=" + branchVsBaseComment + ": New
Tests (" + newTestsCount + ")|" +
+ "borderStyle=dashed|borderColor=#ccc|titleBGColor=" + bgColor
+ "}\\n";
+
+ newTests.insert(0, hdrPanel)
+ .append("{panel}");
+ }
+ else {
+
newTests.append("{panel:title=").append(branchVsBaseComment).append(": No new
tests found!|")
+
.append("borderStyle=dashed|borderColor=#ccc|titleBGColor=#F7D6C1}{panel}");
+ }
+
+ res.append("\\n").append(newTests).append("\\n").append("[TeamCity
*").append(suiteNameForComment).append("* Results|").append(webUrl).append(']');
return xmlEscapeText(res.toString());
}
diff --git a/ignite-tc-helper-web/src/main/webapp/js/testfails-2.2.js
b/ignite-tc-helper-web/src/main/webapp/js/testfails-2.2.js
index 0424aec..09eb64b 100644
--- a/ignite-tc-helper-web/src/main/webapp/js/testfails-2.2.js
+++ b/ignite-tc-helper-web/src/main/webapp/js/testfails-2.2.js
@@ -83,11 +83,57 @@ function showChainResultsWithSettings(result, settings) {
res += showChainCurrentStatusData(server, settings);
}
+ res += "<tr bgcolor='#F5F5FF'><th colspan='4' class='table-title'><b>New
Tests</b></th></tr>"
+
+ for (var i = 0; i < result.servers.length; i++) {
+ var newTests = result.servers[i].newTestsUi;
+ res += showNewTestsData(newTests, settings);
+ }
+
+ res += "<tr><td colspan='4'> </td></tr>";
+ res += "</table>";
+
setTimeout(initMoreInfo, 100);
return res;
}
+/**
+ * @param chain - see
org.apache.ignite.ci.web.model.current.ChainAtServerCurrentStatus Java Class.
+ * @param settings - see Settings JavaScript class.
+ */
+function showNewTestsData(chain, settings) {
+ var res = "";
+
+ newTestRows = "";
+
+ res += "<table style='width:100%'>";
+
+ for (var i = 0; i < chain.length; i++) {
+ var newTests = chain[i].tests;
+ for (var j = 0; j < newTests.length; j++) {
+ newTestsFounded = true
+ var newTest = newTests[j];
+ testColor = newTest.status ? "#013220" : "#8b0000";
+ newTestRows += "<tr style='color:" + testColor + "'>";
+ newTestRows += "<td colspan='2' width='10%'></td>";
+ newTestRows += "<td width='5%'>" + (newTest.status ? "PASSED" :
"FAILED") + "</td>";
+ if (isDefinedAndFilled(newTest.suiteName) &&
isDefinedAndFilled(newTest.testName))
+ newTestRows += "<td width='75%'>" + newTest.suiteName + ": " +
newTest.testName + "</td>";
+ else
+ newTestRows += "<td width='75%'>" + newTest.name + "</td>";
+ newTestRows += "<td colspan='2' width='10%'></td>";
+ newTestRows += "</tr>";
+ }
+ }
+
+ res += newTestRows !== "" ? newTestRows : "<tr><td colspan='2'
width='10%'></td><td width='90%'>No new tests</td></tr>"
+
+ res += "</table>";
+
+ return res;
+
+}
/**
* @param chain - see
org.apache.ignite.ci.web.model.current.ChainAtServerCurrentStatus Java Class.
@@ -320,9 +366,6 @@ function showChainCurrentStatusData(chain, settings) {
res += showSuiteData(subSuite, settings, chain.prNum);
}
- res += "<tr><td colspan='4'> </td></tr>";
- res += "</table>";
-
return res;
}
diff --git
a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java
b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java
index 1a59dd4..a8ae186 100644
---
a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java
+++
b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java
@@ -50,6 +50,7 @@ import
org.apache.ignite.ci.teamcity.ignited.TeamcityIgnitedProviderMock;
import org.apache.ignite.tcbot.common.conf.IDataSourcesConfigSupplier;
import org.apache.ignite.tcbot.common.conf.TcBotWorkDir;
import org.apache.ignite.tcignited.buildlog.IBuildLogProcessor;
+import org.apache.ignite.tcservice.ITeamcityConn;
import org.mockito.Mockito;
import static org.mockito.ArgumentMatchers.any;
@@ -78,6 +79,8 @@ public class MockBasedTcBotModule extends AbstractModule {
bind(IBuildLogProcessor.class).toInstance(Mockito.mock(IBuildLogProcessor.class));
+
bind(ITeamcityConn.class).toInstance(Mockito.mock(ITeamcityConn.class));
+
final IGitHubConnectionProvider ghProv =
Mockito.mock(IGitHubConnectionProvider.class);
bind(IGitHubConnectionProvider.class).toInstance(ghProv);
when(ghProv.server(anyString())).thenReturn(Mockito.mock(IGitHubConnection.class));
diff --git
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/chain/TestCompactedMult.java
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/chain/TestCompactedMult.java
index 9863364..199bdea 100644
---
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/chain/TestCompactedMult.java
+++
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/chain/TestCompactedMult.java
@@ -64,7 +64,15 @@ public class TestCompactedMult {
public String getName() {
return occurrences.isEmpty() ? "" :
occurrences.iterator().next().testName(compactor);
}
-
+
+ public Long getId() {
+ return occurrences.isEmpty() ? 0 :
occurrences.iterator().next().getTestId();
+ }
+
+ public boolean isPassed() {
+ return occurrences.get(occurrences.size()-1).status() ==
STATUS_SUCCESS_CID;
+ }
+
public boolean isInvestigated() {
return occurrences.stream().anyMatch(ITest::isInvestigated);
}
diff --git
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/pr/PrChainsProcessor.java
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/pr/PrChainsProcessor.java
index 8cfaffa..25c17fb 100644
---
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/pr/PrChainsProcessor.java
+++
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/pr/PrChainsProcessor.java
@@ -27,6 +27,7 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import javax.inject.Inject;
+import javax.inject.Provider;
import org.apache.ignite.ci.github.PullRequest;
import org.apache.ignite.githubignited.IGitHubConnIgnited;
import org.apache.ignite.githubignited.IGitHubConnIgnitedProvider;
@@ -46,7 +47,9 @@ import org.apache.ignite.tcbot.engine.conf.ITrackedChain;
import org.apache.ignite.tcbot.engine.ui.DsChainUi;
import org.apache.ignite.tcbot.engine.ui.DsSummaryUi;
import org.apache.ignite.tcbot.engine.ui.ShortSuiteUi;
+import org.apache.ignite.tcbot.engine.ui.ShortSuiteNewTestsUi;
import org.apache.ignite.tcbot.engine.ui.ShortTestFailureUi;
+import org.apache.ignite.tcbot.engine.ui.ShortTestUi;
import org.apache.ignite.tcbot.persistence.IStringCompactor;
import org.apache.ignite.tcignited.ITeamcityIgnited;
import org.apache.ignite.tcignited.ITeamcityIgnitedProvider;
@@ -56,6 +59,8 @@ import org.apache.ignite.tcignited.buildref.BranchEquivalence;
import org.apache.ignite.tcignited.creds.ICredentialsProv;
import org.apache.ignite.tcignited.history.IRunHistory;
import org.apache.ignite.tcservice.ITeamcity;
+import org.apache.ignite.tcservice.ITeamcityConn;
+import org.apache.ignite.tcservice.TeamcityServiceConnection;
/**
* Process pull request/untracked branch chain at particular server.
@@ -87,8 +92,12 @@ public class PrChainsProcessor {
@Inject private ITcBotConfig cfg;
@Inject private BranchEquivalence branchEquivalence;
+
@Inject private UpdateCountersStorage countersStorage;
+ /** Teamcity connection non-caching factory. */
+ @Inject private Provider<ITeamcityConn> tcFactory;
+
/**
* @param creds Credentials.
* @param srvCodeOrAlias Server code or alias.
@@ -113,6 +122,9 @@ public class PrChainsProcessor {
@Nullable Boolean checkAllLogs,
SyncMode mode) {
final DsSummaryUi res = new DsSummaryUi();
+
+ ITeamcityConn teamcityConn = getTeamCityConnection(srvCodeOrAlias,
creds);
+
ITeamcityIgnited tcIgnited = tcIgnitedProvider.server(srvCodeOrAlias,
creds);
IGitHubConnIgnited gitHubConnIgnited =
gitHubConnIgnitedProvider.server(srvCodeOrAlias);
@@ -167,7 +179,7 @@ public class PrChainsProcessor {
//fail rate reference is always default (master)
chainStatus.initFromContext(tcIgnited, ctx, baseBranchForTc,
compactor, false,
null, null, -1, null, false, false); // don't need for PR
-
+ chainStatus.findNewTests(ctx, tcIgnited, baseBranchForTc,
compactor, teamcityConn);
initJiraAndGitInfo(chainStatus, jiraIntegration,
gitHubConnIgnited);
}
@@ -285,6 +297,47 @@ public class PrChainsProcessor {
}
/**
+ * @param buildTypeId Build type ID, for which visa was ordered.
+ * @param branchForTc Branch for TeamCity.
+ * @param srvCodeOrAlias Server id.
+ * @param prov Credentials.
+ * @param syncMode
+ * @param baseBranchForTc
+ * @return List of suites with possible blockers.
+ */
+ @Nullable
+ public List<ShortSuiteNewTestsUi> getNewTestsSuitesStatuses(
+ String buildTypeId,
+ String branchForTc,
+ String srvCodeOrAlias,
+ ICredentialsProv prov,
+ SyncMode syncMode,
+ @Nullable String baseBranchForTc) {
+ ITeamcityIgnited tcIgnited = tcIgnitedProvider.server(srvCodeOrAlias,
prov);
+
+ List<Integer> hist = tcIgnited.getLastNBuildsFromHistory(buildTypeId,
branchForTc, 1);
+
+ String baseBranch = Strings.isNullOrEmpty(baseBranchForTc) ?
dfltBaseTcBranch(srvCodeOrAlias) : baseBranchForTc;
+
+ FullChainRunCtx ctx = buildChainProcessor.loadFullChainContext(
+ tcIgnited,
+ hist,
+ LatestRebuildMode.LATEST,
+ ProcessLogsMode.SUITE_NOT_COMPLETE,
+ false,
+ baseBranch,
+ syncMode,
+ null, null);
+
+ if (ctx.isFakeStub())
+ return null;
+
+ ITeamcityConn teamcityConn = getTeamCityConnection(srvCodeOrAlias,
prov);
+
+ return findNewTests(ctx, tcIgnited, teamcityConn, baseBranch,
branchForTc);
+ }
+
+ /**
* @return Blocker failures for given server.
* @param fullChainRunCtx
* @param tcIgnited
@@ -329,6 +382,49 @@ public class PrChainsProcessor {
.collect(Collectors.toList());
}
+ /**
+ * @return New tests for given server.
+ * @param fullChainRunCtx
+ * @param tcIgnited
+ * @param baseBranch
+ */
+ //todo may avoid creation of UI model for simple comment.
+ private List<ShortSuiteNewTestsUi> findNewTests(FullChainRunCtx
fullChainRunCtx,
+ ITeamcityIgnited tcIgnited,
+ ITeamcityConn teamcityConn,
+ String baseBranch,
+ String branchForTc) {
+ String normalizedBaseBranch =
BranchEquivalence.normalizeBranch(baseBranch);
+ Integer baseBranchId =
compactor.getStringIdIfPresent(normalizedBaseBranch);
+
+ return fullChainRunCtx
+ .suites()
+ .map((ctx) -> {
+ List<ShortTestUi> missingTests = ctx.getFilteredTests(test -> {
+ IRunHistory history = test.history(tcIgnited,
baseBranchId, null);
+ if (history == null) {
+ Long testId = test.getId();
+ return
!teamcityConn.isTestOccurrencesInOtherBranches(testId, branchForTc);
+ }
+ else
+ return false;
+ })
+ .stream()
+ .map(occurrence -> new ShortTestUi().initFrom(occurrence,
occurrence.isPassed()))
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+
+ if (!missingTests.isEmpty()) {
+ return new ShortSuiteNewTestsUi()
+ .tests(missingTests)
+ .initFrom(ctx);
+ }
+ return null;
+ })
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ }
+
public Map<Integer, Integer> getPrUpdateCounters(String srvCodeOrAlias,
String branchForTc, String tcBaseBranchParm,
ICredentialsProv creds) {
String baseBranchForTc = Strings.isNullOrEmpty(tcBaseBranchParm) ?
dfltBaseTcBranch(srvCodeOrAlias) : tcBaseBranchParm;
@@ -339,4 +435,15 @@ public class PrChainsProcessor {
return countersStorage.getCounters(allRelatedBranchCodes);
}
+
+ public ITeamcityConn getTeamCityConnection(String srvCode,
ICredentialsProv prov) {
+ TeamcityServiceConnection conn = (TeamcityServiceConnection)
tcFactory.get();
+ ITcServerConfig cfg = this.cfg.getTeamcityConfig(srvCode);
+ String ref = cfg.reference();
+ String realSrvCode = !Strings.isNullOrEmpty(ref) &&
!srvCode.equals(ref) ? ref : srvCode;
+ conn.setAuthData(prov.getUser(realSrvCode),
prov.getPassword(realSrvCode));
+ conn.init(realSrvCode);
+
+ return conn;
+ }
}
diff --git
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsChainUi.java
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsChainUi.java
index bc8f2da..69d176a 100644
---
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsChainUi.java
+++
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/DsChainUi.java
@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.apache.ignite.internal.util.typedef.T2;
@@ -34,6 +35,8 @@ import org.apache.ignite.tcbot.engine.chain.TestCompactedMult;
import org.apache.ignite.tcbot.engine.tracked.DisplayMode;
import org.apache.ignite.tcbot.persistence.IStringCompactor;
import org.apache.ignite.tcignited.ITeamcityIgnited;
+import org.apache.ignite.tcignited.history.IRunHistory;
+import org.apache.ignite.tcservice.ITeamcityConn;
import org.apache.ignite.tcservice.model.conf.BuildType;
import static
org.apache.ignite.tcbot.engine.ui.DsSuiteUi.createOccurForLogConsumer;
@@ -91,6 +94,9 @@ public class DsChainUi {
/** Suites involved in chain. */
public List<DsSuiteUi> suites = new ArrayList<>();
+ /** Suites with new tests involved in chain. */
+ public List<ShortSuiteNewTestsUi> newTestsUi = new ArrayList<>();
+
/** Count of failed tests not muted tests. In case several runs are used,
overall by all runs. */
public Integer failedTests;
@@ -285,6 +291,43 @@ public class DsChainUi {
);
}
+ public void findNewTests(FullChainRunCtx ctx,
+ ITeamcityIgnited tcIgnited,
+ String baseBranchTc,
+ IStringCompactor compactor,
+ ITeamcityConn teamcityConn){
+ String failRateNormalizedBranch = normalizeBranch(baseBranchTc);
+ Integer baseBranchId =
compactor.getStringIdIfPresent(failRateNormalizedBranch);
+ newTestsUi = ctx
+ .suites()
+ .map((suite) -> {
+ List<ShortTestUi> missingTests = suite.getFilteredTests(test
-> {
+ IRunHistory history = test.history(tcIgnited,
baseBranchId, null);
+ if (history == null) {
+ Long testId = test.getId();
+ return
!teamcityConn.isTestOccurrencesInOtherBranches(testId, branchName);
+ }
+ else
+ return false;
+ })
+ .stream()
+ .map(occurrence -> {
+ ShortTestUi tst = new
ShortTestUi().initFrom(occurrence, occurrence.isPassed());
+ return tst;
+ })
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ if (!missingTests.isEmpty()) {
+ return new ShortSuiteNewTestsUi()
+ .tests(missingTests)
+ .initFrom(suite);
+ }
+ return null;
+ })
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ }
+
private static String buildWebLinkToBuild(ITeamcityIgnited teamcity,
FullChainRunCtx chain) {
return teamcity.host() + "viewLog.html?buildId=" +
chain.getSuiteBuildId();
}
diff --git
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/ShortSuiteNewTestsUi.java
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/ShortSuiteNewTestsUi.java
new file mode 100644
index 0000000..8bfb2e5
--- /dev/null
+++
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/ShortSuiteNewTestsUi.java
@@ -0,0 +1,46 @@
+/*
+ * 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.tcbot.engine.ui;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.apache.ignite.tcbot.engine.chain.MultBuildRunCtx;
+
+public class ShortSuiteNewTestsUi extends DsHistoryStatUi {
+ /** Suite Name */
+ public String name;
+
+ public List<ShortTestUi> tests = new ArrayList<>();
+
+ public Collection<? extends ShortTestUi> tests() {
+ return tests;
+ }
+
+ public ShortSuiteNewTestsUi tests(List<ShortTestUi> tests) {
+ this.tests = tests;
+
+ return this;
+ }
+
+ public ShortSuiteNewTestsUi initFrom(@Nonnull MultBuildRunCtx suite) {
+ name = suite.suiteName();
+
+ return this;
+ }
+}
diff --git
a/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/ShortTestUi.java
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/ShortTestUi.java
new file mode 100644
index 0000000..247b496
--- /dev/null
+++
b/tcbot-engine/src/main/java/org/apache/ignite/tcbot/engine/ui/ShortTestUi.java
@@ -0,0 +1,68 @@
+/*
+ * 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.tcbot.engine.ui;
+
+import com.google.common.base.Strings;
+import org.apache.ignite.tcbot.engine.chain.TestCompactedMult;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+public class ShortTestUi {
+ /** Test full Name */
+ public String name;
+
+ /** suite (in code) short name */
+ @Nullable public String suiteName;
+
+ /** test short name with class and method */
+ @Nullable public String testName;
+
+
+ /** Test status */
+ @Nullable public boolean status;
+
+ public ShortTestUi initFrom(@Nonnull TestCompactedMult testCompactedMult,
boolean status) {
+ name = testCompactedMult.getName();
+
+ String[] split = Strings.nullToEmpty(name).split("\\:");
+ if (split.length >= 2) {
+ this.suiteName = extractSuite(split[0]);
+ this.testName = extractTest(split[1]);
+ }
+
+ this.status = status;
+
+ return this;
+ }
+
+ public static String extractTest(String s) {
+ String testShort = s.trim();
+ String[] testComps = testShort.split("\\.");
+ if (testComps.length > 2)
+ return testComps[testComps.length - 2] + "." +
testComps[testComps.length - 1];
+ return null;
+ }
+
+ public static String extractSuite(String s) {
+ String suiteShort = s.trim();
+ String[] suiteComps = suiteShort.split("\\.");
+ if (suiteComps.length > 1)
+ return suiteComps[suiteComps.length - 1];
+ return null;
+ }
+}
diff --git
a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/ITeamcityConn.java
b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/ITeamcityConn.java
index 6013c2c..7e39aab 100644
---
a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/ITeamcityConn.java
+++
b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/ITeamcityConn.java
@@ -180,4 +180,11 @@ public interface ITeamcityConn {
* @throws IllegalStateException if some unexpected HTTP error returned.
*/
@Nullable public File downloadAndCacheBuildLog(int buildId);
+
+ /**
+ * @param testId test id
+ * @param branchName branch name
+ * @return is the test was run on other branches
+ */
+ public boolean isTestOccurrencesInOtherBranches(Long testId, String
branchName);
}
diff --git
a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/TeamcityServiceConnection.java
b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/TeamcityServiceConnection.java
index bc8e825..3184534 100644
---
a/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/TeamcityServiceConnection.java
+++
b/tcbot-teamcity/src/main/java/org/apache/ignite/tcservice/TeamcityServiceConnection.java
@@ -377,6 +377,16 @@ public class TeamcityServiceConnection implements
ITeamcity {
return sendGetXmlParseJaxb(url, TestOccurrencesFull.class);
}
+ /** {@inheritDoc} */
+ @Override public boolean isTestOccurrencesInOtherBranches(Long testId,
String branchName) {
+ String url = host() +
"app/rest/latest/testOccurrences?locator=test:id:" + testId +
+ ",count:100&fields=testOccurrence(id,name,test,build)";
+ TestOccurrencesFull testOccurrencesFull = sendGetXmlParseJaxb(url,
TestOccurrencesFull.class);
+ boolean testMatch = testOccurrencesFull.getTests().stream()
+ .anyMatch(test -> !test.build.branchName().contains(branchName));
+ return testMatch;
+ }
+
/**
* @param buildId Build id.
* @param testDtls request test details string