Skip to content
Permalink
Browse files
Board: Displaying each test details added - Fixes #153.
Signed-off-by: Dmitriy Pavlov <dpavlov@apache.org>
  • Loading branch information
dspavlov committed Aug 15, 2019
1 parent 7af40e7 commit 47c4121ebaeda1bd9fa7168cc767dea2b2653106
Show file tree
Hide file tree
Showing 7 changed files with 282 additions and 92 deletions.
@@ -28,7 +28,7 @@
public static final String GITHUB_REF = "https://github.com/apache/ignite-teamcity-bot";

/** TC Bot Version. */
public static final String VERSION = "20190814";
public static final String VERSION = "20190815";

/** Java version, where Web App is running. */
public String javaVer;
@@ -54,7 +54,8 @@
{text: "Commits", value: 'blameCandidateSummary'},
{text: "Issues", value: 'cntissues'},
{text: "Fixed", value: 'fixedissues'},
{text: "Not Fixed", value: 'notfixedissues'},
{text: "Ignored", value: 'cntignoredissues'},
{text: "Not Fixed", value: 'cntfailingissues'},
{text: "Unclear", value: 'unclearissues'}
]
},
@@ -183,11 +184,24 @@
</div>

Tests affected:
<div v-for="(test) in item.testOrSuitesAffected">
{{ test }}
</div>

<button v-on:click="onResolve(item.id)">Resolve</button>
<table>
<tr v-for="(issue) in item.allIssues">
<td v-if="issue.status === 'FIXED'">
Fixed
</td>
<td v-else-if="issue.status === 'FAILING'">
Still Failing
</td>
<td v-else>
{{ issue.status }}
</td>

<td>{{ issue.issueType }}</td>
<td>{{ issue.name }}</td>
</tr>
</table>

<button v-if="item.cntFailingIssues === 0" v-on:click="onResolve(item.id)">Resolve</button>
</td>
</template>

@@ -209,8 +223,13 @@
<template v-slot:item.fixedIssues="{ item }">
<span class='visaStage' style="background: #12AD5E" v-if="item.fixedIssues!=null" > {{ item.fixedIssues }} </span>
</template>
<template v-slot:item.notFixedIssues="{ item }" >
<span class='visaStage' style="background: red" v-if="item.notFixedIssues!=null" > {{ item.notFixedIssues }} </span>
<template v-slot:item.cntIgnoredIssues="{ item }">
<span class='visaStage' style="background: darkorange"
v-if="item.cntIgnoredIssues!=0"
:title="item.summaryIgnoredIssues"> {{ item.cntIgnoredIssues }} </span>
</template>
<template v-slot:item.cntFailingIssues="{ item }" >
<span class='visaStage' style="background: red" v-if="item.cntFailingIssues!=0" :title="item.summaryFailingIssues"> {{ item.cntFailingIssues }} </span>
</template>

<template v-slot:item.unclearIssues="{ item }" >
@@ -23,14 +23,15 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import javax.inject.Inject;

import com.google.common.base.Preconditions;
import org.apache.ignite.ci.issue.Issue;
import org.apache.ignite.ci.issue.IssueKey;
import org.apache.ignite.ci.teamcity.ignited.change.ChangeCompacted;
@@ -49,6 +50,7 @@
import org.apache.ignite.tcbot.engine.defect.DefectsStorage;
import org.apache.ignite.tcbot.engine.issue.IIssuesStorage;
import org.apache.ignite.tcbot.engine.issue.IssueType;
import org.apache.ignite.tcbot.engine.ui.BoardDefectIssueUi;
import org.apache.ignite.tcbot.engine.ui.BoardDefectSummaryUi;
import org.apache.ignite.tcbot.engine.ui.BoardSummaryUi;
import org.apache.ignite.tcbot.engine.user.IUserStorage;
@@ -87,7 +89,7 @@ public BoardSummaryUi summary(ICredentialsProv creds) {

String srvCode = next.tcSrvCode(compactor);

if(!creds.hasAccess(srvCode))
if (!creds.hasAccess(srvCode))
continue;

ITeamcityIgnited tcIgn = tcProv.server(srvCode, creds);
@@ -96,7 +98,6 @@ public BoardSummaryUi summary(ICredentialsProv creds) {

List<BlameCandidate> candidates = next.blameCandidates();


Map<Integer, DefectFirstBuild> build = next.buildsInvolved();
for (DefectFirstBuild cause : build.values()) {
FatBuildCompacted firstBuild = cause.build();
@@ -107,47 +108,77 @@ public BoardSummaryUi summary(ICredentialsProv creds) {

Stream<FatBuildCompacted> results = FutureUtil.getResults(futures);
List<FatBuildCompacted> freshRebuild = results.collect(Collectors.toList());
if(!freshRebuild.isEmpty()) {
FatBuildCompacted buildCompacted = freshRebuild.get(0);

for (DefectIssue issue : cause.issues()) {
Optional<ITest> any = buildCompacted.getAllTests()
.filter(t -> t.testName() == issue.testNameCid())
.findAny();

if(any.isPresent()) {
boolean failed = any.get().isFailedTest(compactor);
if(!failed)
defectUi.addFixedIssue();
else
defectUi.addNotFixedIssue();
} else {
//exception for new test. removal of test means test is fixed
if(IssueType.newContributedTestFailure.code().equals(compactor.getStringFromId(issue.issueTypeCode())))
defectUi.addFixedIssue();
else
defectUi.addUnclearIssue();
}

defectUi.addIssue(compactor.getStringFromId(issue.testNameCid()));
}
} else {
for (DefectIssue issue : cause.issues()) {
defectUi.addUnclearIssue();

defectUi.addIssue(compactor.getStringFromId(issue.testNameCid()));
}

Optional<FatBuildCompacted> rebuild;

rebuild = !freshRebuild.isEmpty() ? freshRebuild.stream().findFirst() : Optional.empty();

for (DefectIssue issue : cause.issues()) {
BoardDefectIssueUi issueUi = processIssue(defectUi, rebuild, issue);

defectUi.addIssue(compactor.getStringFromId(issue.testNameCid()), issueUi);
}
}

defectUi.branch = next.tcBranch(compactor);
defectUi.branch = next.tcBranch(compactor);

res.addDefect(defectUi);
}

return res;
}

public BoardDefectIssueUi processIssue(BoardDefectSummaryUi defectUi, Optional<FatBuildCompacted> rebuild,
DefectIssue issue) {
Optional<ITest> testResult;

if (rebuild.isPresent()) {
testResult = rebuild.get().getAllTests()
.filter(t -> t.testName() == issue.testNameCid())
.findAny();
}
else
testResult = Optional.empty();

IssueResolveStatus status;
if (testResult.isPresent()) {
ITest test = testResult.get();

if (test.isIgnoredTest() || test.isMutedTest())
status = IssueResolveStatus.IGNORED;
else {
boolean failed = test.isFailedTest(compactor);
if (!failed) {
defectUi.addFixedIssue();

status = IssueResolveStatus.FIXED;
}
else {
defectUi.addNotFixedIssue();

status = IssueResolveStatus.FAILING;

}
}
} else{
//exception for new test. removal of test means test is fixed
if (IssueType.newContributedTestFailure.code().equals(compactor.getStringFromId(issue.issueTypeCode()))) {
defectUi.addFixedIssue();

status = IssueResolveStatus.FIXED;
}
else {
defectUi.addUnclearIssue();
status = IssueResolveStatus.UNKNOWN;
}
}

return new BoardDefectIssueUi(status,
compactor, issue,
issue.testNameCid(),
issue.issueTypeCode());
}

public void issuesToDefectsLater() {
scheduler.sheduleNamed("issuesToDefects", this::issuesToDefects, 15, TimeUnit.MINUTES);
}
@@ -207,53 +238,56 @@ protected String issuesToDefects() {

defect.removeOldVerBlameCandidates();

if(defect.blameCandidates().isEmpty()) {
//save changes because it can be missed in older DB versions
defect.changeMap(changeDao.getAll(srvId, fatBuild.changes()));

Map<Integer, ChangeCompacted> map = defect.changeMap();
if(defect.blameCandidates().isEmpty())
fillBlameCandidates(srvId, fatBuild, defect);

Collection<ChangeCompacted> values = map.values();
for (ChangeCompacted change : values) {
BlameCandidate candidate = new BlameCandidate();
int vcsUsernameCid = change.vcsUsername();
candidate.vcsUsername(vcsUsernameCid);

int tcUserUsername = change.tcUserUsername();
@Nullable TcHelperUser tcHelperUser = null;
if (tcUserUsername != -1)
tcHelperUser = userStorage.getUser(compactor.getStringFromId(tcUserUsername));
else {
String strVcsUsername = compactor.getStringFromId(vcsUsernameCid);

if(!Strings.isNullOrEmpty(strVcsUsername) &&
strVcsUsername.contains("<") && strVcsUsername.contains(">")) {
int emailStartIdx = strVcsUsername.indexOf('<');
int emailEndIdx = strVcsUsername.indexOf('>');
String email = strVcsUsername.substring(emailStartIdx + 1, emailEndIdx);
tcHelperUser = userStorage.findUserByEmail(email);
}
}
return defect;
});

});

if (tcHelperUser != null) {
String username = tcHelperUser.username();
return cntDefects.get() + " defects processed for " + cntIssues.get() + " issues checked";
}

String fullName = tcHelperUser.fullName();
candidate.fullDisplayName(compactor.getStringId(fullName));
candidate.tcHelperUserUsername(compactor.getStringId(username));
}
private void fillBlameCandidates(int srvId, FatBuildCompacted fatBuild, DefectCompacted defect) {
//save changes because it can be missed in older DB versions
defect.changeMap(changeDao.getAll(srvId, fatBuild.changes()));

Map<Integer, ChangeCompacted> map = defect.changeMap();

Collection<ChangeCompacted> values = map.values();
for (ChangeCompacted change : values) {
BlameCandidate candidate = new BlameCandidate();
int vcsUsernameCid = change.vcsUsername();
candidate.vcsUsername(vcsUsernameCid);

int tcUserUsername = change.tcUserUsername();
@Nullable TcHelperUser tcHelperUser = null;
if (tcUserUsername != -1)
tcHelperUser = userStorage.getUser(compactor.getStringFromId(tcUserUsername));
else {
String strVcsUsername = compactor.getStringFromId(vcsUsernameCid);

if(!Strings.isNullOrEmpty(strVcsUsername) &&
strVcsUsername.contains("<") && strVcsUsername.contains(">")) {
int emailStartIdx = strVcsUsername.indexOf('<');
int emailEndIdx = strVcsUsername.indexOf('>');
String email = strVcsUsername.substring(emailStartIdx + 1, emailEndIdx);
tcHelperUser = userStorage.findUserByEmail(email);
}
}

defect.addBlameCandidate(candidate);
}
}

return defect;
});
if (tcHelperUser != null) {
String username = tcHelperUser.username();

});
String fullName = tcHelperUser.fullName();
candidate.fullDisplayName(compactor.getStringId(fullName));
candidate.tcHelperUserUsername(compactor.getStringId(username));
}

return cntDefects.get() + " defects processed for " + cntIssues.get() + " issues checked";
defect.addBlameCandidate(candidate);
}
}

public void resolveDefect(Integer defectId, ICredentialsProv creds) {
@@ -0,0 +1,21 @@
/*
* 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.board;

public enum IssueResolveStatus {
FIXED, FAILING, IGNORED, UNKNOWN
}

0 comments on commit 47c4121

Please sign in to comment.