Skip to content
Permalink
Browse files
Highlight newly added tests in TC bot visa #166
Signed-off-by: Ivan Rakov <ivan.glukos@gmail.com>
  • Loading branch information
sergeyuttsel authored and glukos committed Jun 16, 2020
1 parent 4194d17 commit 5079361e0c762ef96be43f57be1c32ffd3912ff8
Showing 9 changed files with 376 additions and 8 deletions.
@@ -44,6 +44,8 @@
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());
@@ -69,7 +69,9 @@
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;
@@ -829,13 +831,17 @@ public Visa notifyJira(
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);
@@ -862,7 +868,7 @@ public Visa notifyJira(
* @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);

@@ -910,6 +916,61 @@ private String generateJiraComment(List<ShortSuiteUi> suites, String webUrl, Str
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 + "] ");
@@ -929,7 +990,24 @@ private String generateJiraComment(List<ShortSuiteUi> suites, String webUrl, Str
.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());
}
@@ -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'>&nbsp;</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.
@@ -325,9 +371,6 @@ function showChainCurrentStatusData(chain, settings) {
res += showSuiteData(subSuite, settings, chain.prNum);
}

res += "<tr><td colspan='4'>&nbsp;</td></tr>";
res += "</table>";

return res;
}

@@ -52,6 +52,7 @@
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;
@@ -64,7 +64,15 @@ public static void resetCached() {
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);
}
@@ -27,6 +27,7 @@
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.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.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,6 +92,7 @@ private static class Action {
@Inject private ITcBotConfig cfg;

@Inject private BranchEquivalence branchEquivalence;

@Inject private UpdateCountersStorage countersStorage;

/**
@@ -113,6 +119,7 @@ public DsSummaryUi getTestFailuresSummary(
@Nullable Boolean checkAllLogs,
SyncMode mode) {
final DsSummaryUi res = new DsSummaryUi();

ITeamcityIgnited tcIgnited = tcIgnitedProvider.server(srvCodeOrAlias, creds);

IGitHubConnIgnited gitHubConnIgnited = gitHubConnIgnitedProvider.server(srvCodeOrAlias);
@@ -167,7 +174,7 @@ else if (Action.CHAIN.equals(act))
//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);
initJiraAndGitInfo(chainStatus, jiraIntegration, gitHubConnIgnited);
}

@@ -284,6 +291,45 @@ public List<ShortSuiteUi> getBlockersSuitesStatuses(
return findBlockerFailures(ctx, tcIgnited, baseBranch);
}

/**
* @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;

return findNewTests(ctx, tcIgnited, baseBranch);
}

/**
* @return Blocker failures for given server.
* @param fullChainRunCtx
@@ -329,6 +375,42 @@ private List<ShortSuiteUi> findBlockerFailures(FullChainRunCtx fullChainRunCtx,
.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,
String baseBranch) {
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);
return history == null;
})
.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;

0 comments on commit 5079361

Please sign in to comment.