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
The following commit(s) were added to refs/heads/master by this push: new e16e00d Ignite gg 14609 (#105) e16e00d is described below commit e16e00d7e5df2d207ce4c68467f0c3331828bad6 Author: Dmitriy Pavlov <dpav...@apache.org> AuthorDate: Fri Jan 11 18:33:18 2019 +0300 Ignite gg 14609 (#105) IGNITE-GG-14609: Phase 1 implemented --- .../java/org/apache/ignite/ci/HelperConfig.java | 2 +- .../main/java/org/apache/ignite/ci/ITeamcity.java | 12 -- .../apache/ignite/ci/IgnitePersistentTeamcity.java | 51 +++++--- .../apache/ignite/ci/IgniteTeamcityConnection.java | 11 +- .../main/java/org/apache/ignite/ci/TcHelper.java | 1 + .../org/apache/ignite/ci/conf/PasswordEncoder.java | 2 +- .../org/apache/ignite/ci/github/GitHubBranch.java | 6 + .../ci/github/ignited/GitHubConnIgnitedImpl.java | 26 +++- .../ci/github/ignited/IGitHubConnIgnited.java | 9 ++ .../ci/github/pure/GitHubConnectionImpl.java | 13 +- .../ignite/ci/github/pure/IGitHubConnection.java | 10 +- .../apache/ignite/ci/jira/IJiraIntegration.java | 5 +- .../main/java/org/apache/ignite/ci/jira/Jira.java | 13 +- .../ignite/ci/jira/ignited/JiraTicketSync.java | 4 +- .../ignite/ci/runners/GenerateStatusHtml.java | 4 +- .../runners/IgniteTeamcityHelperRunnerExample.java | 6 +- .../tcbot/visa/TcBotTriggerAndSignOffService.java | 142 ++++++++++++++------- .../org/apache/ignite/ci/tcmodel/conf/Project.java | 13 +- .../conf/{Project.java => ProjectsList.java} | 52 +++----- .../ci/teamcity/ignited/ITeamcityIgnited.java | 2 + .../ci/teamcity/ignited/TeamcityIgnitedImpl.java | 10 +- .../teamcity/ignited/buildtype/BuildTypeSync.java | 9 +- .../ignite/ci/teamcity/pure/ITeamcityConn.java | 6 + .../apache/ignite/ci/web/IBackgroundUpdatable.java | 2 +- .../java/org/apache/ignite/ci/web/Launcher.java | 5 +- .../model/current/ChainAtServerCurrentStatus.java | 2 +- .../ignite/ci/web/model/current/UpdateInfo.java | 8 +- .../ignite/ci/web/rest/pr/GetPrTestFailures.java | 32 ++--- .../ignite/ci/web/rest/visa/TcBotVisaService.java | 7 +- ignite-tc-helper-web/src/main/webapp/js/prs-1.0.js | 50 ++++---- .../src/main/webapp/js/testfails-2.1.js | 16 +-- ignite-tc-helper-web/src/main/webapp/prs.html | 17 +-- 32 files changed, 297 insertions(+), 251 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 dc08958..f773100 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 @@ -63,7 +63,7 @@ public class HelperConfig { /** JIRA URL to build links to tickets. */ public static final String JIRA_URL = "jira.url"; - /** Template for JIRA ticket names. */ + /** Prefix for JIRA ticket names. */ public static final String JIRA_TICKET_TEMPLATE = "jira.ticket_template"; /** Slack authorization token property name. */ 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 4a62cb7..fa1f3a7 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 @@ -52,18 +52,6 @@ public interface ITeamcity extends ITeamcityConn { /** Temporary feature toggle: Use New run stat in PR analysis, issue detection. */ boolean NEW_RUN_STAT = true; - /** {@inheritDoc} */ - @Override default List<BuildType> getBuildTypes(String projectId) { - return FutureUtil.getResult(getProjectSuites(projectId)); - } - - /** - * List of project suites. - * - * @param projectId Project id. - */ - CompletableFuture<List<BuildType>> getProjectSuites(String projectId); - /** */ @Deprecated CompletableFuture<List<BuildRef>> getQueuedBuilds(@Nullable String branch); 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 61ec4fc..76db429 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 @@ -19,10 +19,30 @@ package org.apache.ignite.ci; import com.google.common.base.Strings; import com.google.common.base.Throwables; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.List; import java.util.SortedSet; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; +import javax.annotation.Nullable; +import javax.inject.Inject; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCache; -import org.apache.ignite.ci.analysis.*; +import org.apache.ignite.ci.analysis.Expirable; +import org.apache.ignite.ci.analysis.IVersionedEntity; +import org.apache.ignite.ci.analysis.LogCheckResult; +import org.apache.ignite.ci.analysis.RunStat; +import org.apache.ignite.ci.analysis.SingleBuildRunCtx; +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.di.AutoProfiling; @@ -31,36 +51,19 @@ import org.apache.ignite.ci.tcmodel.agent.Agent; import org.apache.ignite.ci.tcmodel.changes.Change; import org.apache.ignite.ci.tcmodel.changes.ChangesList; import org.apache.ignite.ci.tcmodel.conf.BuildType; +import org.apache.ignite.ci.tcmodel.conf.Project; import org.apache.ignite.ci.tcmodel.conf.bt.BuildTypeFull; import org.apache.ignite.ci.tcmodel.hist.BuildRef; import org.apache.ignite.ci.tcmodel.mute.MuteInfo; import org.apache.ignite.ci.tcmodel.result.Build; import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrences; import org.apache.ignite.ci.tcmodel.result.stat.Statistics; -import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrence; import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrencesFull; import org.apache.ignite.ci.tcmodel.user.User; -import org.apache.ignite.ci.teamcity.ignited.IRunStat; -import org.apache.ignite.ci.util.CollectionUtil; import org.apache.ignite.ci.util.ObjectInterner; import org.apache.ignite.ci.web.model.hist.VisasHistoryStorage; import org.jetbrains.annotations.NotNull; -import javax.annotation.Nullable; -import javax.cache.Cache; -import javax.inject.Inject; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.Comparator; -import java.util.List; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - import static org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync.normalizeBranch; /** @@ -160,8 +163,8 @@ public class IgnitePersistentTeamcity implements IAnalyticsEnabledTeamcity, ITea /** {@inheritDoc} */ @AutoProfiling - @Override public CompletableFuture<List<BuildType>> getProjectSuites(String projectId) { - return teamcity.getProjectSuites(projectId); + @Override public List<BuildType> getBuildTypes(String projectId) { + return teamcity.getBuildTypes(projectId); } /** {@inheritDoc} */ @@ -489,6 +492,7 @@ public class IgnitePersistentTeamcity implements IAnalyticsEnabledTeamcity, ITea return teamcity.triggerBuild(buildTypeId, branchName, cleanRebuild, queueAtTop); } + /** {@inheritDoc} */ @Override public ProblemOccurrences getProblems(int buildId) { return teamcity.getProblems(buildId); } @@ -503,6 +507,11 @@ public class IgnitePersistentTeamcity implements IAnalyticsEnabledTeamcity, ITea return problems; } + /** {@inheritDoc} */ + @Override public List<Project> getProjects() { + return teamcity.getProjects(); + } + @Override public Statistics getStatistics(int buildId) { return teamcity.getStatistics(buildId); } diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java index cd88aea..50c707f 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java @@ -33,6 +33,7 @@ import org.apache.ignite.ci.tcmodel.changes.Change; import org.apache.ignite.ci.tcmodel.changes.ChangesList; import org.apache.ignite.ci.tcmodel.conf.BuildType; import org.apache.ignite.ci.tcmodel.conf.Project; +import org.apache.ignite.ci.tcmodel.conf.ProjectsList; import org.apache.ignite.ci.tcmodel.conf.bt.BuildTypeFull; import org.apache.ignite.ci.tcmodel.hist.BuildRef; import org.apache.ignite.ci.tcmodel.hist.Builds; @@ -342,9 +343,10 @@ public class IgniteTeamcityConnection implements ITeamcity { return getJaxbUsingHref(href, ChangesList.class); } + /** {@inheritDoc} */ @AutoProfiling @Override public Change getChange(int changeId) { - String href = "app/rest/latest/changes/id:" + + changeId +""; + String href = "app/rest/latest/changes/id:" + +changeId; return getJaxbUsingHref(href, Change.class); } @@ -370,11 +372,12 @@ public class IgniteTeamcityConnection implements ITeamcity { } /** {@inheritDoc} */ - @Override public CompletableFuture<List<BuildType>> getProjectSuites(String projectId) { - return supplyAsync(() -> getProjectSuitesSync(projectId), executor); + @Override public List<Project> getProjects() { + return sendGetXmlParseJaxb(host + "app/rest/latest/projects", ProjectsList.class).projects(); } - private List<BuildType> getProjectSuitesSync(String projectId) { + /** {@inheritDoc} */ + @Override public List<BuildType> getBuildTypes(String projectId) { return sendGetXmlParseJaxb(host + "app/rest/latest/projects/" + projectId, Project.class) .getBuildTypesNonNull(); } diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/TcHelper.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/TcHelper.java index f4e8c09..cbd550b 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/TcHelper.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/TcHelper.java @@ -156,6 +156,7 @@ public class TcHelper implements ITcHelper { try { List<SuiteCurrentStatus> suitesStatuses = prChainsProcessor.getBlockersSuitesStatuses(buildTypeId, build.branchName, srvId, prov); + if (suitesStatuses == null) return new Visa("JIRA wasn't commented - no finished builds to analyze."); diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/conf/PasswordEncoder.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/conf/PasswordEncoder.java index f6be3e4..97788d9 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/conf/PasswordEncoder.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/conf/PasswordEncoder.java @@ -90,7 +90,7 @@ public class PasswordEncoder { } public static void main(String[] args) { - String pass = "ddd"; + String pass = "324aadfe23...."; String encode = encode(pass); System.err.println("Encoded: " + HelperConfig.GITHUB_AUTH_TOKEN + "=" + encode); String decode = decode(encode); diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/GitHubBranch.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/GitHubBranch.java index a4b3dea..92d4475 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/GitHubBranch.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/GitHubBranch.java @@ -23,6 +23,7 @@ public class GitHubBranch { private String ref; private String sha; + /** {@inheritDoc} */ @Override public boolean equals(Object o) { if (this == o) return true; @@ -34,7 +35,12 @@ public class GitHubBranch { Objects.equal(sha, branch.sha); } + /** {@inheritDoc} */ @Override public int hashCode() { return Objects.hashCode(label, ref, sha); } + + public String ref() { + return ref; + } } diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/ignited/GitHubConnIgnitedImpl.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/ignited/GitHubConnIgnitedImpl.java index 29a85a1..2838936 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/ignited/GitHubConnIgnitedImpl.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/ignited/GitHubConnIgnitedImpl.java @@ -36,6 +36,7 @@ import org.apache.ignite.ci.di.MonitoredTask; import org.apache.ignite.ci.di.scheduler.IScheduler; import org.apache.ignite.ci.github.PullRequest; import org.apache.ignite.ci.github.pure.IGitHubConnection; +import org.jetbrains.annotations.NotNull; /** * @@ -79,10 +80,14 @@ class GitHubConnIgnitedImpl implements IGitHubConnIgnited { } /** {@inheritDoc} */ + @Override public void notifyGit(String url, String body) { + conn.notifyGit(url, body); + } + + /** {@inheritDoc} */ @AutoProfiling @Override public List<PullRequest> getPullRequests() { - scheduler.sheduleNamed(IGitHubConnIgnited.class.getSimpleName() + ".actualizePrs", - this::actualizePrs, 2, TimeUnit.MINUTES); + scheduler.sheduleNamed(taskName("actualizePrs"), this::actualizePrs, 2, TimeUnit.MINUTES); return StreamSupport.stream(prCache.spliterator(), false) .filter(entry -> entry.getKey() >> 32 == srvIdMaskHigh) @@ -91,6 +96,16 @@ class GitHubConnIgnitedImpl implements IGitHubConnIgnited { .collect(Collectors.toList()); } + /** + * @param taskName Task name. + * @return Task name concatenated with server name. + */ + @NotNull + private String taskName(String taskName) { + return IGitHubConnIgnited.class.getSimpleName() + "." + taskName + "." + srvId; + } + + private void actualizePrs() { runActualizePrs(srvId, false); @@ -102,8 +117,7 @@ class GitHubConnIgnitedImpl implements IGitHubConnIgnited { * */ private void sheduleResync() { - scheduler.sheduleNamed(IGitHubConnIgnited.class.getSimpleName() + ".fullReindex", - this::fullReindex, 60, TimeUnit.MINUTES); + scheduler.sheduleNamed(taskName("fullReindex"), this::fullReindex, 60, TimeUnit.MINUTES); } /** @@ -157,14 +171,14 @@ class GitHubConnIgnitedImpl implements IGitHubConnIgnited { @SuppressWarnings({"WeakerAccess", "UnusedReturnValue"}) @MonitoredTask(name = "Check Outdated PRs(srv)", nameExtArgsIndexes = {0}) protected String refreshOutdatedPrs(String srvId, Set<Integer> actualPrs) { - final long count = StreamSupport.stream(prCache.spliterator(), false) + final long cnt = StreamSupport.stream(prCache.spliterator(), false) .filter(entry -> entry.getKey() >> 32 == srvIdMaskHigh) .filter(entry -> PullRequest.OPEN.equals(entry.getValue().getState())) .filter(entry -> !actualPrs.contains(entry.getValue().getNumber())) .peek(entry -> prCache.put(entry.getKey(), conn.getPullRequest(entry.getValue().getNumber()))) .count(); - return "PRs updated for " + srvId + ": " + count + " from " + prCache.size(); + return "PRs updated for " + srvId + ": " + cnt + " from " + prCache.size(); } private int saveChunk(List<PullRequest> ghData) { diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/ignited/IGitHubConnIgnited.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/ignited/IGitHubConnIgnited.java index d532589..81d36c9 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/ignited/IGitHubConnIgnited.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/ignited/IGitHubConnIgnited.java @@ -45,4 +45,13 @@ public interface IGitHubConnIgnited { return getPullRequest(prId); } + + /** + * Send POST request with given body. + * + * @param url Url. + * @param body Request body. + * @return {@code True} - if GitHub was notified. {@code False} - otherwise. + */ + void notifyGit(String url, String body); } diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/pure/GitHubConnectionImpl.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/pure/GitHubConnectionImpl.java index 60aa34f..f3f177c 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/pure/GitHubConnectionImpl.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/pure/GitHubConnectionImpl.java @@ -111,16 +111,6 @@ class GitHubConnectionImpl implements IGitHubConnection { /** {@inheritDoc} */ @AutoProfiling - @Override public PullRequest getPullRequest(String branchForTc) { - Integer prId = IGitHubConnection.convertBranchToId(branchForTc); - - Preconditions.checkNotNull(prId, "Invalid TC branch name"); - - return getPullRequest(prId); - } - - /** {@inheritDoc} */ - @AutoProfiling @Override public boolean notifyGit(String url, String body) { try { HttpUtil.sendPostAsStringToGit(gitAuthTok, url, body); @@ -165,9 +155,10 @@ class GitHubConnectionImpl implements IGitHubConnection { List<PullRequest> list = new Gson().fromJson(reader, listType); String link = rspHeaders.get("Link"); - if (link != null) { + if (link != null) { String nextLink = parseNextLinkFromLinkRspHeader(link); + if (nextLink != null) outLinkNext.set(nextLink); } diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/pure/IGitHubConnection.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/pure/IGitHubConnection.java index 03c3c82..2bf08ca 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/pure/IGitHubConnection.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/github/pure/IGitHubConnection.java @@ -22,16 +22,12 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.ignite.ci.github.PullRequest; import org.jetbrains.annotations.Nullable; +/** + * + */ public interface IGitHubConnection { - void init(String srvId); - /** - * @param branch TeamCity's branch name. Looks like "pull/123/head". - * @return Pull Request. - */ - PullRequest getPullRequest(String branch); - /** */ PullRequest getPullRequest(Integer id); diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/IJiraIntegration.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/IJiraIntegration.java index 7e9caa3..c66a736 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/IJiraIntegration.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/IJiraIntegration.java @@ -19,6 +19,7 @@ package org.apache.ignite.ci.jira; import org.apache.ignite.ci.web.model.Visa; import org.apache.ignite.ci.user.ICredentialsProv; +import org.jetbrains.annotations.NotNull; /** * Reperesents methods to provide interaction with Jira servers. @@ -55,8 +56,8 @@ public interface IJiraIntegration { /** */ public String jiraUrl(); - /** */ - public String ticketTemplate(); + /** @return JIRA ticket prefix. */ + @NotNull public String ticketPrefix(); /** */ public void init(String srvId); diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Jira.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Jira.java index aff3e46..b413193 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Jira.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Jira.java @@ -25,6 +25,7 @@ import org.apache.ignite.ci.HelperConfig; import org.apache.ignite.ci.ITcHelper; import org.apache.ignite.ci.user.ICredentialsProv; import org.apache.ignite.ci.web.model.Visa; +import org.jetbrains.annotations.NotNull; import static com.google.common.base.Strings.isNullOrEmpty; @@ -38,8 +39,8 @@ public class Jira implements IJiraIntegration { /** */ private String jiraUrl; - /** */ - private String jiraTicketTemplate; + /** JIRA ticket prefix. */ + @NotNull private String jiraTicketPrefix; /** {@inheritDoc} */ @Override public void init(String srvId) { @@ -50,8 +51,8 @@ public class Jira implements IJiraIntegration { final Properties props = HelperConfig.loadAuthProperties(workDir, cfgName); jiraUrl = props.getProperty(HelperConfig.JIRA_URL); - jiraTicketTemplate = props.getProperty(HelperConfig.JIRA_TICKET_TEMPLATE, - "IGNITE-"); + + jiraTicketPrefix = props.getProperty(HelperConfig.JIRA_TICKET_TEMPLATE, "IGNITE-"); } /** {@inheritDoc} */ @@ -60,8 +61,8 @@ public class Jira implements IJiraIntegration { } /** {@inheritDoc} */ - @Override public String ticketTemplate() { - return jiraTicketTemplate; + @Override public String ticketPrefix() { + return jiraTicketPrefix; } /** {@inheritDoc} */ diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraTicketSync.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraTicketSync.java index a5b5f3c..b7fbfd7 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraTicketSync.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraTicketSync.java @@ -69,7 +69,7 @@ public class JiraTicketSync { if (F.isEmpty(page)) return "Something went wrong - no tickets found. Check jira availability."; - jiraDao.saveChunk(srvIdMaskHigh, page, jira.ticketTemplate()); + jiraDao.saveChunk(srvIdMaskHigh, page, jira.ticketPrefix()); int ticketsSaved = page.size(); @@ -84,7 +84,7 @@ public class JiraTicketSync { if (F.isEmpty(page)) break; - jiraDao.saveChunk(srvIdMaskHigh, page, jira.ticketTemplate()); + jiraDao.saveChunk(srvIdMaskHigh, page, jira.ticketPrefix()); ticketsSaved += page.size(); } diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/GenerateStatusHtml.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/GenerateStatusHtml.java index c986665..a987ff1 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/GenerateStatusHtml.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/GenerateStatusHtml.java @@ -277,12 +277,12 @@ public class GenerateStatusHtml { private static ProjectStatus getBuildStatuses( final String tcId, final String projectId, - final List<Branch> branchesPriv) throws Exception { + final List<Branch> branchesPriv) { ProjectStatus projStatus = new ProjectStatus(); final IgniteTeamcityConnection teamcityHelper = TcConnectionStaticLinker.create(tcId); - List<BuildType> suites = teamcityHelper.getProjectSuites(projectId).get(); + List<BuildType> suites = teamcityHelper.getBuildTypes(projectId); for (BuildType buildType : suites) { if (!"-> Run All".equals(buildType.getName()) diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/IgniteTeamcityHelperRunnerExample.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/IgniteTeamcityHelperRunnerExample.java index 1c4500e..05ff217 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/IgniteTeamcityHelperRunnerExample.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/runners/IgniteTeamcityHelperRunnerExample.java @@ -49,7 +49,7 @@ public class IgniteTeamcityHelperRunnerExample { int k = 0; if (k > 0) { //branch example: "pull/2335/head" - List<BuildType> buildTypes = helper.getProjectSuites("Ignite20Tests").get(); + List<BuildType> buildTypes = helper.getBuildTypes("Ignite20Tests"); } @@ -70,10 +70,10 @@ public class IgniteTeamcityHelperRunnerExample { } } - private static void checkBuildTypes(IgniteTeamcityConnection helper) throws InterruptedException, ExecutionException { + private static void checkBuildTypes(IgniteTeamcityConnection helper) { Map<String, Set<String>> duplicates = new TreeMap<>(); Map<String, String> suiteToBt = new TreeMap<>(); - List<BuildType> buildTypes = helper.getProjectSuites("Ignite20Tests").get(); + List<BuildType> buildTypes = helper.getBuildTypes("Ignite20Tests"); for (BuildType bt : buildTypes) { final BuildTypeFull type = helper.getBuildType(bt.getId()); if ("Ignite20Tests_RunAll".equals(type.getId()) 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 aecc4d1..1ed9dfd 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 @@ -36,8 +36,10 @@ import javax.ws.rs.QueryParam; import org.apache.ignite.ci.HelperConfig; import org.apache.ignite.ci.ITcHelper; import org.apache.ignite.ci.ITeamcity; +import org.apache.ignite.ci.github.GitHubBranch; import org.apache.ignite.ci.github.GitHubUser; import org.apache.ignite.ci.github.PullRequest; +import org.apache.ignite.ci.github.ignited.IGitHubConnIgnited; import org.apache.ignite.ci.github.ignited.IGitHubConnIgnitedProvider; import org.apache.ignite.ci.github.pure.IGitHubConnection; import org.apache.ignite.ci.github.pure.IGitHubConnectionProvider; @@ -46,8 +48,8 @@ import org.apache.ignite.ci.jira.IJiraIntegrationProvider; import org.apache.ignite.ci.observer.BuildObserver; import org.apache.ignite.ci.observer.BuildsInfo; import org.apache.ignite.ci.tcbot.chain.PrChainsProcessor; -import org.apache.ignite.ci.tcmodel.result.Build; import org.apache.ignite.ci.tcmodel.mute.MuteInfo; +import org.apache.ignite.ci.tcmodel.result.Build; import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted; import org.apache.ignite.ci.teamcity.ignited.IStringCompactor; import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited; @@ -55,11 +57,11 @@ import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider; import org.apache.ignite.ci.teamcity.ignited.SyncMode; import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeCompacted; import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeRefCompacted; -import org.apache.ignite.ci.web.model.ContributionKey; -import org.apache.ignite.ci.web.model.VisaRequest; -import org.apache.ignite.ci.web.model.Visa; import org.apache.ignite.ci.user.ICredentialsProv; +import org.apache.ignite.ci.web.model.ContributionKey; import org.apache.ignite.ci.web.model.SimpleResult; +import org.apache.ignite.ci.web.model.Visa; +import org.apache.ignite.ci.web.model.VisaRequest; import org.apache.ignite.ci.web.model.current.SuiteCurrentStatus; import org.apache.ignite.ci.web.model.hist.VisasHistoryStorage; import org.apache.ignite.internal.util.typedef.F; @@ -69,7 +71,6 @@ import org.jetbrains.annotations.Nullable; import static org.apache.ignite.ci.observer.BuildsInfo.CANCELLED_STATUS; import static org.apache.ignite.ci.observer.BuildsInfo.FINISHED_STATUS; import static org.apache.ignite.ci.observer.BuildsInfo.RUNNING_STATUS; -import static org.apache.ignite.ci.teamcity.ignited.TeamcityIgnitedImpl.DEFAULT_PROJECT_ID; import static org.apache.ignite.ci.web.rest.parms.FullQueryParams.DEFAULT_TRACKED_BRANCH_NAME; /** @@ -83,23 +84,21 @@ public class TcBotTriggerAndSignOffService { } }; + /** Build observer provider. */ @Inject Provider<BuildObserver> buildObserverProvider; - /** Git hub pure http connection provider. */ - @Inject IGitHubConnectionProvider gitHubConnectionProvider; + /** GitHub (pure) HTTP connection provider. */ + @Inject IGitHubConnectionProvider gitHubConnProvider; - /** Git hub connection ignited provider. */ + /** GitHub connection ignited provider. */ @Inject IGitHubConnIgnitedProvider gitHubConnIgnitedProvider; + /** TC ignited provider. */ @Inject ITeamcityIgnitedProvider tcIgnitedProv; /** */ @Inject IJiraIntegrationProvider jiraIntegrationProvider; - @Inject ITeamcityIgnitedProvider teamcityIgnitedProvider; - - @Inject Provider<BuildObserver> observer; - /** */ @Inject private VisasHistoryStorage visasHistoryStorage; @@ -180,7 +179,7 @@ public class TcBotTriggerAndSignOffService { * @return Mutes for given server-project pair. */ public Set<MuteInfo> getMutes(String srvId, String projectId, ICredentialsProv creds) { - ITeamcityIgnited ignited = teamcityIgnitedProvider.server(srvId, creds); + ITeamcityIgnited ignited = tcIgnitedProv.server(srvId, creds); Set<MuteInfo> infos = ignited.getMutes(projectId, creds); @@ -194,17 +193,28 @@ public class TcBotTriggerAndSignOffService { * @param pr Pull Request. * @return JIRA ticket full name or empty string. */ + @Deprecated @NotNull public static String getTicketFullName(PullRequest pr) { - String ticketId = ""; + String prefix = "IGNITE-"; + + return getTicketFullName(pr, prefix); + } - if (pr.getTitle().toUpperCase().startsWith("IGNITE-")) { - int beginIdx = 7; - int endIdx = 7; + /** + * @param pr Pull Request. + * @param prefix Ticket prefix. + * @return JIRA ticket full name or empty string. + */ + @NotNull public static String getTicketFullName(PullRequest pr, @NotNull String prefix) { + String ticketId = ""; + if (pr.getTitle().toUpperCase().startsWith(prefix)) { + int beginIdx = prefix.length(); + int endIdx = prefix.length(); while (endIdx < pr.getTitle().length() && Character.isDigit(pr.getTitle().charAt(endIdx))) endIdx++; - ticketId = "IGNITE-" + pr.getTitle().substring(beginIdx, endIdx); + ticketId = prefix + pr.getTitle().substring(beginIdx, endIdx); } return ticketId; @@ -252,17 +262,21 @@ public class TcBotTriggerAndSignOffService { String parentSuiteId, Build... builds ) { + IJiraIntegration jiraIntegration = jiraIntegrationProvider.server(srvId); + + String prefix = jiraIntegration.ticketPrefix(); + if (F.isEmpty(ticketFullName)) { try { - IGitHubConnection gitHubConn = gitHubConnectionProvider.server(srvId); + IGitHubConnIgnited gitHubConn = gitHubConnIgnitedProvider.server(srvId); PullRequest pr = gitHubConn.getPullRequest(branchForTc); - ticketFullName = getTicketFullName(pr); + ticketFullName = getTicketFullName(pr, prefix); if (ticketFullName.isEmpty()) { return "JIRA ticket will not be notified after the tests are completed - " + - "PR title \"" + pr.getTitle() + "\" should starts with \"IGNITE-XXXX\"." + + "PR title \"" + pr.getTitle() + "\" should starts with \"" + prefix + "-NNNNN\"." + " Please, rename PR according to the" + " <a href='https://cwiki.apache.org/confluence/display/IGNITE/How+to+Contribute" + "#HowtoContribute-1.CreateGitHubpull-request'>contributing guide</a>."; @@ -274,8 +288,8 @@ public class TcBotTriggerAndSignOffService { e.getMessage() + ']'; } } else { - //todo remove once every ticket is with IGnite prefix - ticketFullName = ticketFullName.toUpperCase().startsWith("IGNITE-") ? ticketFullName : "IGNITE-" + ticketFullName; + //todo remove once every ticket is with Ignite prefix + ticketFullName = ticketFullName.toUpperCase().startsWith(prefix) ? ticketFullName : prefix + ticketFullName; } buildObserverProvider.get().observe(srvId, prov, ticketFullName, branchForTc, parentSuiteId, builds); @@ -283,8 +297,7 @@ public class TcBotTriggerAndSignOffService { if (!tcHelper.isServerAuthorized()) return "Ask server administrator to authorize the Bot to enable JIRA notifications."; - return "JIRA ticket IGNITE-" + ticketFullName + - " will be notified after the tests are completed."; + return "JIRA ticket " + ticketFullName + " will be notified after the tests are completed."; } /** @@ -303,16 +316,20 @@ public class TcBotTriggerAndSignOffService { ICredentialsProv prov) { String jiraRes = ""; + IJiraIntegration jiraIntegration = jiraIntegrationProvider.server(srvId); + + String prefix = jiraIntegration.ticketPrefix(); + if (Strings.isNullOrEmpty(ticketFullName)) { try { - IGitHubConnection gitHubConn = gitHubConnectionProvider.server(srvId); + IGitHubConnIgnited gitHubConn = gitHubConnIgnitedProvider.server(srvId); PullRequest pr = gitHubConn.getPullRequest(branchForTc); - ticketFullName = getTicketFullName(pr); + ticketFullName = getTicketFullName(pr, prefix); if (ticketFullName.isEmpty()) { jiraRes = "JIRA ticket can't be commented - " + - "PR title \"" + pr.getTitle() + "\" should starts with \"IGNITE-XXXX\"." + + "PR title \"" + pr.getTitle() + "\" should starts with \"" + prefix + "NNNNN\"." + " Please, rename PR according to the" + " <a href='https://cwiki.apache.org/confluence/display/IGNITE/How+to+Contribute" + "#HowtoContribute-1.CreateGitHubpull-request'>contributing guide</a>" + @@ -324,7 +341,7 @@ public class TcBotTriggerAndSignOffService { } } else { //todo remove once every ticket is with IGnite prefix - ticketFullName = ticketFullName.toUpperCase().startsWith("IGNITE-") ? ticketFullName : "IGNITE-" + ticketFullName; + ticketFullName = ticketFullName.toUpperCase().startsWith(prefix) ? ticketFullName : prefix + ticketFullName; } if (!Strings.isNullOrEmpty(ticketFullName)) { @@ -337,12 +354,10 @@ public class TcBotTriggerAndSignOffService { " \"Re-run possible blockers & Comment JIRA\" was triggered for current branch." + " Wait for the end or cancel exsiting observing."); - IJiraIntegration jiraIntegration = jiraIntegrationProvider.server(srvId); Visa visa = jiraIntegration.notifyJira(srvId, prov, suiteId, branchForTc, ticketFullName); - visasHistoryStorage.put(new VisaRequest(buildsInfo) - .setResult(visa)); + visasHistoryStorage.put(new VisaRequest(buildsInfo).setResult(visa)); return new SimpleResult(visa.status); } @@ -373,7 +388,8 @@ public class TcBotTriggerAndSignOffService { check.prAuthorAvatarUrl = user.avatarUrl(); } - check.jiraIssueId = Strings.emptyToNull(getTicketFullName(pr)); + String prefix = jiraIntegration.ticketPrefix(); + check.jiraIssueId = Strings.emptyToNull(getTicketFullName(pr, prefix)); if (!Strings.isNullOrEmpty(check.jiraIssueId)) check.jiraIssueUrl = jiraIntegration.generateTicketUrl(check.jiraIssueId); @@ -382,10 +398,9 @@ public class TcBotTriggerAndSignOffService { }).collect(Collectors.toList()); } - @Nonnull private List<BuildRefCompacted> findBuildsForPr(String suiteId, String prId, ITeamcityIgnited srv) { - - String branchName = branchForTcA(prId); - List<BuildRefCompacted> buildHist = srv.getAllBuildsCompacted(suiteId, branchName); + @Nonnull private List<BuildRefCompacted> findBuildsForPr(String suiteId, String prId, + IGitHubConnIgnited ghConn, ITeamcityIgnited srv) { + List<BuildRefCompacted> buildHist = srv.getAllBuildsCompacted(suiteId, branchForTcA(prId)); if (!buildHist.isEmpty()) return buildHist; @@ -395,6 +410,21 @@ public class TcBotTriggerAndSignOffService { if (!buildHist.isEmpty()) return buildHist; + PullRequest pr = ghConn.getPullRequest(Integer.valueOf(prId)); + + if (pr != null) { + GitHubBranch head = pr.head(); + + if (head != null) { + String ref = head.ref(); + + buildHist = srv.getAllBuildsCompacted(suiteId, ref); + + if (!buildHist.isEmpty()) + return buildHist; + } + } + return Collections.emptyList(); } @@ -415,24 +445,44 @@ public class TcBotTriggerAndSignOffService { String prId) { Set<ContributionCheckStatus> statuses = new LinkedHashSet<>(); - ITeamcityIgnited teamcity = teamcityIgnitedProvider.server(srvId, prov); + ITeamcityIgnited teamcity = tcIgnitedProv.server(srvId, prov); + + IGitHubConnIgnited ghConn = gitHubConnIgnitedProvider.server(srvId); StringBuilder buildTypeId = new StringBuilder(); HelperConfig.getTrackedBranches().get(DEFAULT_TRACKED_BRANCH_NAME) - .ifPresent(b -> b.getChainsStream().filter(c -> c.branchForRest.equals(ITeamcity.DEFAULT)) - .findFirst().ifPresent(ch -> buildTypeId.append(ch.suiteId))); + .ifPresent( + b -> b.getChainsStream() + .filter(c -> Objects.equals(srvId, c.serverId)) + .filter(c -> c.branchForRest.equals(ITeamcity.DEFAULT)) + .findFirst() + .ifPresent(ch -> buildTypeId.append(ch.suiteId))); BuildTypeCompacted buildType = buildTypeId.length() > 0 ? teamcity.getBuildType(buildTypeId.toString()) : null; - String projectId = Objects.nonNull(buildType) ? - compactor.getStringFromId(buildType.projectId()) : DEFAULT_PROJECT_ID; + List<String> compositeBuildTypeIds; + String projectId; + if (buildType != null) { + projectId = compactor.getStringFromId(buildType.projectId()); + compositeBuildTypeIds = teamcity.getCompositeBuildTypesIdsSortedByBuildNumberCounter(projectId); + } + else { + //for case build type not found, actualizing all projects resync + List<String> projects = teamcity.getAllProjectsIds(); + + for (String pId : projects) + teamcity.getCompositeBuildTypesIdsSortedByBuildNumberCounter(pId); + + compositeBuildTypeIds = new ArrayList<>(); + + if (buildTypeId.length() > 0) + compositeBuildTypeIds.add(buildTypeId.toString()); + } - List<String> compositeBuildTypeIds = teamcity - .getCompositeBuildTypesIdsSortedByBuildNumberCounter(projectId); for (String btId : compositeBuildTypeIds) { - List<BuildRefCompacted> forTests = findBuildsForPr(btId, prId, teamcity); + List<BuildRefCompacted> forTests = findBuildsForPr(btId, prId, ghConn, teamcity); statuses.add(forTests.isEmpty() ? new ContributionCheckStatus(btId, branchForTcA(prId)) : contributionStatus(srvId, btId, forTests, teamcity, prId)); @@ -472,7 +522,7 @@ public class TcBotTriggerAndSignOffService { else status.resolvedBranch = !builds.isEmpty() ? builds.get(0).branchName(compactor) : branchForTcA(prId); - String observationsStatus = observer.get().getObservationStatus(new ContributionKey(srvId, status.resolvedBranch)); + String observationsStatus = buildObserverProvider.get().getObservationStatus(new ContributionKey(srvId, status.resolvedBranch)); status.observationsStatus = Strings.emptyToNull(observationsStatus); diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/Project.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/Project.java index 8d9b7da..e27736d 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/Project.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/Project.java @@ -29,19 +29,19 @@ import javax.xml.bind.annotation.XmlRootElement; /** * Content of poject */ -@XmlRootElement(name="project") +@XmlRootElement(name = "project") @XmlAccessorType(XmlAccessType.FIELD) public class Project { /** Id. */ @XmlAttribute public String id; /** Name. */ - @XmlAttribute(name="name") + @XmlAttribute(name = "name") private String name; /** Build types. */ - @XmlElementWrapper(name="buildTypes") - @XmlElement(name="buildType") + @XmlElementWrapper(name = "buildTypes") + @XmlElement(name = "buildType") private List<BuildType> buildTypes; /** @@ -60,5 +60,10 @@ public class Project { public String name() { return name; } + + /** */ + public String id() { + return id; + } } diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/Project.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/ProjectsList.java similarity index 52% copy from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/Project.java copy to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/ProjectsList.java index 8d9b7da..1a9594a 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/Project.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/ProjectsList.java @@ -19,46 +19,32 @@ package org.apache.ignite.ci.tcmodel.conf; import java.util.Collections; import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; +import org.apache.ignite.ci.tcmodel.changes.ChangesListRef; +import org.jetbrains.annotations.NotNull; /** - * Content of poject + * List of Projects available at TC. */ -@XmlRootElement(name="project") -@XmlAccessorType(XmlAccessType.FIELD) -public class Project { - /** Id. */ - @XmlAttribute public String id; - - /** Name. */ - @XmlAttribute(name="name") - private String name; - - /** Build types. */ - @XmlElementWrapper(name="buildTypes") - @XmlElement(name="buildType") - private List<BuildType> buildTypes; - - /** - * @return List of project's build types or an empty list if there is no build types presented. - */ - public List<BuildType> getBuildTypesNonNull() { - return buildTypes == null ? Collections.emptyList() : buildTypes; +@XmlRootElement(name = "projects") +public class ProjectsList extends ChangesListRef { + /** Projects. */ + @XmlElement(name = "project") + private List<Project> projects; + + /** Count. */ + @XmlElement Integer count; + + /** {@inheritDoc} */ + @Override public String toString() { + return "ProjectsList{" + + "projects=" + projects + + '}'; } /** */ - public void name(String name) { - this.name = name; - } - - /** */ - public String name() { - return name; + @NotNull public List<Project> projects() { + return projects == null ? Collections.emptyList() : Collections.unmodifiableList(projects); } } - diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java index ead6dd7..16f44e0 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnited.java @@ -177,4 +177,6 @@ public interface ITeamcityIgnited { * @return run statistics of recent runls on all branches. */ @Nullable public IRunStat getSuiteRunStatAllBranches(String suiteBuildTypeId); + + List<String> getAllProjectsIds(); } diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java index 077bb42..65930eb 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java @@ -31,6 +31,7 @@ import org.apache.ignite.ci.jira.ignited.JiraTicketDao; import org.apache.ignite.ci.jira.ignited.JiraTicketSync; import org.apache.ignite.ci.jira.Ticket; import org.apache.ignite.ci.tcbot.trends.MasterTrendsService; +import org.apache.ignite.ci.tcmodel.conf.Project; import org.apache.ignite.ci.tcmodel.mute.MuteInfo; import org.apache.ignite.ci.teamcity.ignited.mute.MuteDao; import org.apache.ignite.ci.teamcity.ignited.mute.MuteSync; @@ -427,9 +428,11 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited { return runHistCompactedDao.getSuiteRunStatAllBranches(srvIdMaskHigh, suiteBuildTypeId); } - /** - * @param branchName Branch name. - */ + /** {@inheritDoc} */ + @Override public List<String> getAllProjectsIds() { + return conn.getProjects().stream().map(Project::id).collect(Collectors.toList()); + } + /** {@inheritDoc} */ @Override public List<String> getCompositeBuildTypesIdsSortedByBuildNumberCounter(String projectId) { return buildTypeSync.getCompositeBuildTypesIdsSortedByBuildNumberCounter(srvIdMaskHigh, projectId, conn); @@ -447,6 +450,7 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited { /** {@inheritDoc} */ @Override public BuildTypeCompacted getBuildType(String buildTypeId) { + return buildTypeDao.getFatBuildType(srvIdMaskHigh, buildTypeId); } diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildtype/BuildTypeSync.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildtype/BuildTypeSync.java index eb5fba5..997429a 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildtype/BuildTypeSync.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/buildtype/BuildTypeSync.java @@ -107,7 +107,7 @@ public class BuildTypeSync { * @param conn Pure HTTP Connection API. */ private void ensureActualizeBuildTypeRefsRequested(int srvIdMaskHigh, String projectId, ITeamcityConn conn) { - scheduler.sheduleNamed(taskName("actualizeAllBuildTypeRefs", conn.serverId()), + scheduler.sheduleNamed(taskName("actualizeAllBuildTypeRefs", conn.serverId(), projectId), () -> reindexBuildTypeRefs(srvIdMaskHigh, projectId, conn), 4, TimeUnit.HOURS); } @@ -119,7 +119,7 @@ public class BuildTypeSync { * @param conn Pure HTTP Connection API. */ private void ensureActualizeBuildTypesRequested(int srvIdMaskHigh, String projectId, ITeamcityConn conn) { - scheduler.sheduleNamed(taskName("actualizeAllBuildTypes", conn.serverId()), + scheduler.sheduleNamed(taskName("actualizeAllBuildTypeRefs", "actualizeAllBuildTypes", conn.serverId()), () -> reindexBuildTypes(srvIdMaskHigh, projectId, conn), 24, TimeUnit.HOURS); } @@ -241,9 +241,10 @@ public class BuildTypeSync { /** * @param taskName Task name. * @param srvName Server name. + * @param prjName Project name. */ @NotNull - private String taskName(String taskName, String srvName) { - return BuildTypeSync.class.getSimpleName() +"." + taskName + "." + srvName; + private String taskName(String taskName, String srvName, String prjName) { + return BuildTypeSync.class.getSimpleName() + "." + taskName + "." + srvName + "." + prjName; } } diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java index 9ebecba..4a1bfeb 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java @@ -26,6 +26,7 @@ import javax.annotation.Nullable; import org.apache.ignite.ci.tcmodel.changes.Change; import org.apache.ignite.ci.tcmodel.changes.ChangesList; import org.apache.ignite.ci.tcmodel.conf.BuildType; +import org.apache.ignite.ci.tcmodel.conf.Project; import org.apache.ignite.ci.tcmodel.conf.bt.BuildTypeFull; import org.apache.ignite.ci.tcmodel.hist.BuildRef; import org.apache.ignite.ci.tcmodel.mute.MuteInfo; @@ -103,4 +104,9 @@ public interface ITeamcityConn { /** */ @Deprecated ProblemOccurrences getProblemsAndRegisterCritical(BuildRef build); + + /** + * @return List of all project available at Teamcity server. + */ + List<Project> getProjects(); } diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/IBackgroundUpdatable.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/IBackgroundUpdatable.java index cd58277..75aeba0 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/IBackgroundUpdatable.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/IBackgroundUpdatable.java @@ -18,7 +18,7 @@ package org.apache.ignite.ci.web; /** - * Created by Дмитрий on 02.11.2017 + * */ public interface IBackgroundUpdatable { /** diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/Launcher.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/Launcher.java index 4ff0f81..2d29ff0 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/Launcher.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/Launcher.java @@ -22,15 +22,18 @@ import java.io.Console; import java.io.File; import java.io.IOException; import java.io.Reader; +import org.apache.ignite.ci.db.TcHelperDb; import org.apache.ignite.ci.tcbot.TcBotSystemProperties; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.webapp.WebAppContext; /** - * Created by Дмитрий on 04.08.2017 + * Launcher for server note and web application: all in one. + * For client only node use {@link LauncherIgniteClientMode} and {@link TcHelperDb} for server. */ public class Launcher { + /** */ public static void main(String[] args) throws Exception { runServer(true); } diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/ChainAtServerCurrentStatus.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/ChainAtServerCurrentStatus.java index 82ee4ec..b1d10ff 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/ChainAtServerCurrentStatus.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/current/ChainAtServerCurrentStatus.java @@ -141,7 +141,7 @@ public class ChainAtServerCurrentStatus { if (pullReq != null && pullReq.getTitle() != null) { prUrl = pullReq.htmlUrl(); - ticketFullName = TcBotTriggerAndSignOffService.getTicketFullName(pullReq); + ticketFullName = TcBotTriggerAndSignOffService.getTicketFullName(pullReq, jiraIntegration.ticketPrefix()); if (!ticketFullName.isEmpty()) ticketUrl = jiraIntegration.generateTicketUrl(ticketFullName); 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 788dd57..381855d 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 @@ -21,7 +21,7 @@ import org.apache.ignite.ci.IAnalyticsEnabledTeamcity; import org.apache.ignite.ci.github.pure.IGitHubConnection; /** - * Created by Дмитрий on 19.02.2018 + * */ @SuppressWarnings("WeakerAccess") public class UpdateInfo { /** TeamCity auth token availability flag. */ @@ -56,14 +56,14 @@ import org.apache.ignite.ci.github.pure.IGitHubConnection; /** * @param teamcity TeamCity to get info about tokens. - * @param gitHubConnection + * @param gitHubConn GitHub integration associated with this server. */ public void setJavaFlags(IAnalyticsEnabledTeamcity teamcity, - IGitHubConnection gitHubConnection) { + IGitHubConnection gitHubConn) { if (teamcity.isTeamCityTokenAvailable()) javaFlags |= TEAMCITY_FLAG; - if (gitHubConnection.isGitTokenAvailable()) + if (gitHubConn.isGitTokenAvailable()) javaFlags |= GITHUB_FLAG; if (teamcity.isJiraTokenAvailable()) 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 a6eeb28..88d9d30 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,31 +17,29 @@ package org.apache.ignite.ci.web.rest.pr; -import javax.ws.rs.FormParam; -import javax.ws.rs.POST; - import com.google.inject.Injector; -import org.apache.ignite.ci.tcbot.chain.PrChainsProcessor; -import org.apache.ignite.ci.github.pure.IGitHubConnection; -import org.apache.ignite.ci.github.pure.IGitHubConnectionProvider; -import org.apache.ignite.ci.github.PullRequest; -import org.apache.ignite.ci.teamcity.ignited.SyncMode; -import org.apache.ignite.ci.user.ICredentialsProv; -import org.apache.ignite.ci.web.CtxListener; -import org.apache.ignite.ci.web.model.current.TestFailuresSummary; -import org.apache.ignite.ci.web.model.current.UpdateInfo; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - import javax.annotation.Nonnull; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.FormParam; import javax.ws.rs.GET; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; +import org.apache.ignite.ci.github.PullRequest; +import org.apache.ignite.ci.github.ignited.IGitHubConnIgnited; +import org.apache.ignite.ci.github.ignited.IGitHubConnIgnitedProvider; +import org.apache.ignite.ci.tcbot.chain.PrChainsProcessor; +import org.apache.ignite.ci.teamcity.ignited.SyncMode; +import org.apache.ignite.ci.user.ICredentialsProv; +import org.apache.ignite.ci.web.CtxListener; +import org.apache.ignite.ci.web.model.current.TestFailuresSummary; +import org.apache.ignite.ci.web.model.current.UpdateInfo; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; @Path(GetPrTestFailures.PR) @Produces(MediaType.APPLICATION_JSON) @@ -137,8 +135,7 @@ public class GetPrTestFailures { return "Given branch is not a pull request. Notify works only for pull requests."; final Injector injector = CtxListener.getInjector(ctx); - final ICredentialsProv creds = ICredentialsProv.get(req); - final IGitHubConnection srv = injector.getInstance(IGitHubConnectionProvider.class).server(srvId); + final IGitHubConnIgnited srv = injector.getInstance(IGitHubConnIgnitedProvider.class).server(srvId); PullRequest pr; @@ -153,7 +150,6 @@ public class GetPrTestFailures { srv.notifyGit(statusesUrl, msg); - return "Git was notified."; } } diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java index adf2c7b..3ce734c 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/visa/TcBotVisaService.java @@ -89,16 +89,13 @@ public class TcBotVisaService { @GET @Path("contributionStatus") public Set<ContributionCheckStatus> contributionStatus(@Nullable @QueryParam("serverId") String srvId, - @Nonnull @QueryParam("suiteId") String suiteId, @QueryParam("prId") String prId) { ICredentialsProv prov = ICredentialsProv.get(req); if (!prov.hasAccess(srvId)) throw ServiceUnauthorizedException.noCreds(srvId); - TcBotTriggerAndSignOffService instance = CtxListener.getInjector(ctx) - .getInstance(TcBotTriggerAndSignOffService.class); - - return instance.contributionStatuses(srvId, prov, prId); + return CtxListener.getInjector(ctx) + .getInstance(TcBotTriggerAndSignOffService.class).contributionStatuses(srvId, prov, prId); } @GET diff --git a/ignite-tc-helper-web/src/main/webapp/js/prs-1.0.js b/ignite-tc-helper-web/src/main/webapp/js/prs-1.0.js index ada8a87..33a05b5 100644 --- a/ignite-tc-helper-web/src/main/webapp/js/prs-1.0.js +++ b/ignite-tc-helper-web/src/main/webapp/js/prs-1.0.js @@ -1,4 +1,4 @@ -function drawTable(srvId, suiteId, element) { +function drawTable(srvId, element) { let tableId = "serverContributions-" + srvId; element.append("<div id='expandAllButton' align='right' style='margin-right:50px'></div><br>" + @@ -17,27 +17,32 @@ function drawTable(srvId, suiteId, element) { " </table>\n"); } -function requestTableForServer(srvId, suiteId, element) { +function requestTableForServer(srvId, suiteIdIgnored, element) { // TODO multiple servers - if (srvId != "apache") + let s = findGetParameter("server"); + if (!isDefinedAndFilled(s)) { + if (srvId !== "apache") + return; + } + else if (srvId !== s) return; // TODO multiple suites - if (suiteId != "IgniteTests24Java8_RunAll") - return; + // if (suiteId != "IgniteTests24Java8_RunAll") + // return; let tableId = "serverContributions-" + srvId; if ($("#" + tableId).length > 0) return; - drawTable(srvId, suiteId, element); + drawTable(srvId, element); $.ajax({ url: "rest/visa/contributions?serverId=" + srvId, success: function (result) { - showContributionsTable(result, srvId, suiteId); + showContributionsTable(result, srvId, ""); fillBranchAutocompleteList(result, srvId); setAutocompleteFilter(); } @@ -144,10 +149,7 @@ function showContributionsTable(result, srvId, suiteId) { "render": function (data, type, row, meta) { let prId = data; if (type === 'display' && isDefinedAndFilled(data)) { - data = "<a id='showReportlink_" + prId + "' href='" + - prShowHref(srvId, suiteId, data) + - "'>" + - "<button id='show_" + prId + "'>Open " + data + "head</button></a>"; + data = " " + data + ""; } return data; @@ -222,7 +224,7 @@ function showStageBlockers(stageNum, prId, blockers) { /* Formatting function for row details - modify as you need */ -function formatContributionDetails(row, srvId, suiteId) { +function formatContributionDetails(row, srvId) { // row is the original data object for the row if(!isDefinedAndFilled(row)) return; @@ -280,7 +282,6 @@ function formatContributionDetails(row, srvId, suiteId) { $.ajax({ url: "rest/visa/contributionStatus" + "?serverId=" + srvId + - "&suiteId=" + suiteId + "&prId=" + prId, success: function (result) { @@ -327,7 +328,7 @@ function formatContributionDetails(row, srvId, suiteId) { return res; } -function repaint(srvId, suiteId) { +function repaint(srvId) { let tableId = 'serverContributions-' + srvId; let datatable = $('#' + tableId).DataTable(); @@ -340,7 +341,7 @@ function repaint(srvId, suiteId) { if (isDefinedAndFilled(row.child)) { if (row.child.isShown()) { // Replaint this row - row.child(formatContributionDetails(row.data(), srvId, suiteId)).show(); + row.child(formatContributionDetails(row.data(), srvId)).show(); } } } @@ -348,13 +349,13 @@ function repaint(srvId, suiteId) { datatable.draw(); } -function repaintLater(srvId, suiteId) { +function repaintLater(srvId) { setTimeout(function () { - repaint(srvId, suiteId) + repaint(srvId) }, 3000); } -function showContributionStatus(status, prId, row, srvId, suiteId) { +function showContributionStatus(status, prId, row, srvId, suiteIdSelected) { let tdForPr = $('#showResultFor' + prId); if (!isDefinedAndFilled(status)) { @@ -369,8 +370,7 @@ function showContributionStatus(status, prId, row, srvId, suiteId) { let queuedStatus = "Has queued builds: " + status.queuedBuilds + " queued " + " " + status.runningBuilds + " running"; let replaintCall = "repaintLater(" + - "\"" + srvId + "\", " + - "\"" + suiteId + "\", " + + "\"" + srvId + "\"" + ");"; var linksToRunningBuilds = ""; @@ -383,7 +383,7 @@ function showContributionStatus(status, prId, row, srvId, suiteId) { if (buildIsCompleted) { let finishedBranch = status.branchWithFinishedSuite; - tdForPr.html("<a id='showReportlink_" + prId + "' href='" + prShowHref(srvId, suiteId, finishedBranch) + "'>" + + tdForPr.html("<a id='showReportlink_" + prId + "' href='" + prShowHref(srvId, suiteIdSelected, finishedBranch) + "'>" + "<button id='show_" + prId + "'>Show " + finishedBranch + " report</button></a>"); if (hasJiraIssue) { @@ -391,7 +391,7 @@ function showContributionStatus(status, prId, row, srvId, suiteId) { "commentJira(" + "\"" + srvId + "\", " + "\"" + finishedBranch + "\", " + - "\"" + suiteId + "\", " + + "\"" + suiteIdSelected + "\", " + "\"" + row.jiraIssueId + "\"" + "); " + replaintCall + @@ -441,7 +441,7 @@ function showContributionStatus(status, prId, row, srvId, suiteId) { let triggerBuildsCall = "triggerBuilds(" + "\"" + srvId + "\", " + "null, " + - "\"" + suiteId + "\", " + + "\"" + suiteIdSelected + "\", " + "\"" + status.resolvedBranch + "\"," + " false," + " false," + @@ -458,7 +458,7 @@ function showContributionStatus(status, prId, row, srvId, suiteId) { let trigObserveCall = "triggerBuilds(" + "\"" + srvId + "\", " + "null, " + - "\"" + suiteId + "\", " + + "\"" + suiteIdSelected + "\", " + "\"" + status.resolvedBranch + "\"," + " false," + " true," + @@ -479,7 +479,7 @@ function showContributionStatus(status, prId, row, srvId, suiteId) { $.ajax({ url: "rest/visa/visaStatus" + "?serverId=" + srvId + - "&suiteId=" + suiteId + + "&suiteId=" + suiteIdSelected + "&tcBranch=" + status.branchWithFinishedSuite, success: function (result) { 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 e5123cf..2950b2f 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 @@ -390,7 +390,7 @@ function triggerBuilds(serverId, parentSuiteId, suiteIdList, branchName, top, ob var suiteIdsNotExists = !isDefinedAndFilled(suiteIdList) || suiteIdList.length === 0; var branchNotExists = !isDefinedAndFilled(branchName) || branchName.length === 0; branchName = branchNotExists ? null : branchForTc(branchName); - ticketId = (isDefinedAndFilled(ticketId) && ticketId.length > 0) ? jiraTicketNumber(ticketId) : null; + ticketId = (isDefinedAndFilled(ticketId) && ticketId.length > 0) ? ticketId : null; var triggerConfirm = $("#triggerConfirm"); @@ -485,22 +485,10 @@ function branchForTc(pr) { return pr; } -/** - * Converts JIRA ticket full name to the tickets number. - * - * @param ticket - JIRA ticket. - * @returns {string} JIRA ticket number. - */ -function jiraTicketNumber(ticket) { - var regExpr = /(ignite-)?(\d*)/i; - - return regExpr.exec(ticket)[2]; -} - function commentJira(serverId, branchName, parentSuiteId, ticketId) { var branchNotExists = !isDefinedAndFilled(branchName) || branchName.length === 0; branchName = branchNotExists ? null : branchForTc(branchName); - ticketId = (isDefinedAndFilled(ticketId) && ticketId.length > 0) ? jiraTicketNumber(ticketId) : null; + ticketId = (isDefinedAndFilled(ticketId) && ticketId.length > 0) ? ticketId : null; if (branchNotExists) { var triggerConfirm = $("#triggerConfirm"); diff --git a/ignite-tc-helper-web/src/main/webapp/prs.html b/ignite-tc-helper-web/src/main/webapp/prs.html index 6284927..6e72d8f 100644 --- a/ignite-tc-helper-web/src/main/webapp/prs.html +++ b/ignite-tc-helper-web/src/main/webapp/prs.html @@ -76,14 +76,11 @@ }); } - - function prShowHref(srvId, suiteId, branchName) { return "/pr.html?serverId=" + srvId + "&" + "suiteId=" + suiteId + //"&baseBranchForTc=" + - "&branchForTc=" + - branchName + + "&branchForTc=" + branchName + "&action=Latest"; } @@ -95,17 +92,13 @@ for (var i = 0; i < result.length; i++) { var chainAtServer = result[i]; - // TODO multiple servers - if (chainAtServer.serverId != "apache") - continue; - res += "Server: <input type='text' name='serverId' value='" + chainAtServer.serverId + "' readonly>"; res += "Chain: <input type='text' name='suiteId' value='" + chainAtServer.suiteId + "' readonly>"; res += "Branch: <input type='text' name='branchForTc' class='branchForTc" + chainAtServer.serverId + "' required> "; res += "Ticket: <input type='text' name='ticketId'>"; res += "<button name='jira' type='button' onclick='trigBuild(\"tests\")'>Start tests</button>"; - res += "<button name='jira' onclick='trigBuild(\"tests+jira\")'>Start tests and comment JIRA ticket on ready</button>"; + res += "<button name='jira' onclick='trigBuild(\"tests+jira\")'>Start tests and comment JIRA ticket on ready</button><br>"; //res += "<button name='git' onclick='trigBuild(\"tests+jira\")'>Start tests and comment GitHub PR on ready</button>"; /* res+="Server: <input type='text' name='serverId' value=" + serverId +" readonly>" ; @@ -126,16 +119,12 @@ for (var i = 0; i < result.length; i++) { var chainAtServer = result[i]; - // TODO multiple servers - if (chainAtServer.serverId != "apache") - continue; - res += "Server: <input type='text' name='serverId' value=" + chainAtServer.serverId +" readonly>" ; res += "Chain: <input type='text' name='suiteId' value='" + chainAtServer.suiteId + "' readonly>"; res += "Branch: <input type='text' name='branchForTc' class='branchForTc" + chainAtServer.serverId + "' required> "; res += "Ticket: <input type='text' name='ticketId'> "; - res += "<button name='action' onclick='notifyJira()'>Notify</button>"; + res += "<button name='action' onclick='notifyJira()'>Notify</button><br>"; } $("#notifyJira").html(res);