This is an automated email from the ASF dual-hosted git repository. dpavlov pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ignite-teamcity-bot.git
commit 5b3f462d43dec616aaa0d601289423cce2ada91e Author: Dmitrii Ryabov <[email protected]> AuthorDate: Thu Dec 13 19:00:51 2018 +0300 IGNITE-10454 Create page with muted tests - Fixes #101. Signed-off-by: Dmitriy Pavlov <[email protected]> --- .../main/java/org/apache/ignite/ci/ITcHelper.java | 11 ++- .../main/java/org/apache/ignite/ci/ITeamcity.java | 6 ++ .../apache/ignite/ci/IgnitePersistentTeamcity.java | 5 ++ .../apache/ignite/ci/IgniteTeamcityConnection.java | 8 ++ .../main/java/org/apache/ignite/ci/TcHelper.java | 20 ++++- .../mute/MuteTarget.java => jira/Fields.java} | 22 ++--- .../apache/ignite/ci/jira/IJiraIntegration.java | 10 +++ .../main/java/org/apache/ignite/ci/jira/Jira.java | 5 ++ .../mute/MuteTarget.java => jira/Status.java} | 29 +++---- .../mute/MuteTarget.java => jira/Ticket.java} | 43 ++++++---- .../mute/MuteAssignment.java => jira/Tickets.java} | 48 ++++++----- .../ignited/JiraTicketDao.java} | 82 ++++++------------- .../ignite/ci/jira/ignited/JiraTicketSync.java | 94 ++++++++++++++++++++++ .../ignite/ci/jira/ignited/TicketCompacted.java | 61 ++++++++++++++ .../tcbot/visa/TcBotTriggerAndSignOffService.java | 2 +- .../ignite/ci/tcmodel/mute/MuteAssignment.java | 2 +- .../apache/ignite/ci/tcmodel/mute/MuteInfo.java | 8 +- .../apache/ignite/ci/tcmodel/mute/MuteScope.java | 2 +- .../apache/ignite/ci/tcmodel/mute/MuteTarget.java | 2 +- .../org/apache/ignite/ci/tcmodel/mute/Mutes.java | 5 +- .../ci/teamcity/ignited/ITeamcityIgnited.java | 4 +- .../ci/teamcity/ignited/TeamcityIgnitedImpl.java | 51 +++++++++++- .../ci/teamcity/ignited/TeamcityIgnitedModule.java | 6 ++ .../ignite/ci/teamcity/ignited/mute/MuteDao.java | 4 +- .../ignite/ci/teamcity/ignited/mute/MuteSync.java | 2 + .../java/org/apache/ignite/ci/util/HttpUtil.java | 34 +++++++- ignite-tc-helper-web/src/main/webapp/mutes.html | 20 +++-- 27 files changed, 435 insertions(+), 151 deletions(-) diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcHelper.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcHelper.java index ba70533..1c084c1 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcHelper.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITcHelper.java @@ -17,8 +17,7 @@ package org.apache.ignite.ci; -import java.util.Collection; -import java.util.List; +import org.apache.ignite.ci.jira.Tickets; import org.apache.ignite.ci.tcbot.issue.IssueDetector; import org.apache.ignite.ci.issue.IssuesStorage; import org.apache.ignite.ci.teamcity.restcached.ITcServerProvider; @@ -65,4 +64,12 @@ public interface ITcHelper extends ITcServerProvider { * @return {@code Visa} which contains info about JIRA notification. */ Visa notifyJira(String srvId, ICredentialsProv prov, String buildTypeId, String branchForTc, String ticket); + + /** + * @param srvId Server id. + * @param prov Credentials. + * @param ticketId Ticket. + * @return Jira tickets. + */ + Tickets getJiraTickets(String srvId, ICredentialsProv prov, String ticketId); } 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 29f0680..4a62cb7 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 @@ -124,6 +124,12 @@ public interface ITeamcity extends ITeamcityConn { public String sendJiraComment(String ticket, String comment) throws IOException; /** + * @param url Url. + * @return Response as gson string. + */ + String sendGetToJira(String url) throws IOException; + + /** * @param url URL for JIRA integration. */ void setJiraApiUrl(String url); 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 08f7a42..23849a2 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 @@ -596,6 +596,11 @@ public class IgnitePersistentTeamcity implements IAnalyticsEnabledTeamcity, ITea } /** {@inheritDoc} */ + @Override public String sendGetToJira(String url) throws IOException { + return teamcity.sendGetToJira(url); + } + + /** {@inheritDoc} */ @Override public void setJiraApiUrl(String url) { teamcity.setJiraApiUrl(url); } 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 af28719..cd88aea 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 @@ -181,6 +181,14 @@ public class IgniteTeamcityConnection implements ITeamcity { } /** {@inheritDoc} */ + @Override public String sendGetToJira(String url) throws IOException { + if (isNullOrEmpty(jiraApiUrl)) + throw new IllegalStateException("JIRA API URL is not configured for this server."); + + return HttpUtil.sendGetToJira(jiraBasicAuthTok, jiraApiUrl + url); + } + + /** {@inheritDoc} */ @Override public void setJiraApiUrl(String url) { jiraApiUrl = url; } 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 c293e91..f4e8c09 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 @@ -18,12 +18,12 @@ package org.apache.ignite.ci; import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.Collection; +import com.google.gson.Gson; import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import javax.inject.Inject; -import org.apache.ignite.ci.conf.BranchesTracked; +import org.apache.ignite.ci.jira.Tickets; import org.apache.ignite.ci.tcbot.issue.IssueDetector; import org.apache.ignite.ci.issue.IssuesStorage; import org.apache.ignite.ci.jira.IJiraIntegration; @@ -184,6 +184,22 @@ public class TcHelper implements ITcHelper { return new Visa(IJiraIntegration.JIRA_COMMENTED, res, blockers); } + /** {@inheritDoc} */ + @Override public Tickets getJiraTickets(String srvId, ICredentialsProv prov, String url) { + IAnalyticsEnabledTeamcity teamcity = server(srvId, prov); + + try { + return new Gson().fromJson(teamcity.sendGetToJira(url), Tickets.class); + } + catch (Exception e) { + String errMsg = "Exception happened during receiving JIRA tickets " + + "[url=" + url + ", errMsg=" + e.getMessage() + ']'; + + logger.error(errMsg); + + return new Tickets(); + } + } /** * @param suites Suite Current Status. diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteTarget.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Fields.java similarity index 60% copy from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteTarget.java copy to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Fields.java index 2d437de..f9aa8e9 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteTarget.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Fields.java @@ -15,22 +15,12 @@ * limitations under the License. */ -package org.apache.ignite.ci.tcmodel.mute; - -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementWrapper; -import org.apache.ignite.ci.tcmodel.result.tests.TestRef; +package org.apache.ignite.ci.jira; /** - * Mute target (e.g. muted test). + * */ -@XmlAccessorType(XmlAccessType.FIELD) -public class MuteTarget { - /** Tests. */ - @XmlElementWrapper(name="tests") - @XmlElement(name="test") - public List<TestRef> tests; -} +public class Fields { + /** Ticket status. */ + public Status status; +} \ No newline at end of file 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 d952b2f..12b3836 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 @@ -42,6 +42,16 @@ public interface IJiraIntegration { public Visa notifyJira(String srvId, ICredentialsProv prov, String buildTypeId, String branchForTc, String ticket); + /** + * Produce wrapper for collection of Jira tickets for given server. + * + * @param srvId Server id. + * @param prov Prov. + * @param ticketId Ticket id. + * @return Jira tickets. + */ + public Tickets getTickets(String srvId, ICredentialsProv prov, String ticketId); + /** */ public String jiraUrl(); 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 b23d840..8755b90 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 @@ -61,6 +61,11 @@ public class Jira implements IJiraIntegration { } /** {@inheritDoc} */ + @Override public Tickets getTickets(String srvId, ICredentialsProv prov, String url) { + return helper.getJiraTickets(srvId, prov, url); + } + + /** {@inheritDoc} */ @Override public String generateTicketUrl(String ticketFullName) { Preconditions.checkState(!isNullOrEmpty(jiraUrl), "Jira URL is not configured for this server."); diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteTarget.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Status.java similarity index 60% copy from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteTarget.java copy to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Status.java index 2d437de..62ceeb3 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteTarget.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Status.java @@ -15,22 +15,19 @@ * limitations under the License. */ -package org.apache.ignite.ci.tcmodel.mute; - -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementWrapper; -import org.apache.ignite.ci.tcmodel.result.tests.TestRef; +package org.apache.ignite.ci.jira; /** - * Mute target (e.g. muted test). + * Status for Jira ticket. */ -@XmlAccessorType(XmlAccessType.FIELD) -public class MuteTarget { - /** Tests. */ - @XmlElementWrapper(name="tests") - @XmlElement(name="test") - public List<TestRef> tests; -} +public class Status { + /** Status text (open, resolved, etc). */ + public String name; + + /** + * @param name Name. + */ + public Status(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteTarget.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Ticket.java similarity index 57% copy from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteTarget.java copy to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Ticket.java index 2d437de..f69c1bf 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteTarget.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Ticket.java @@ -15,22 +15,33 @@ * limitations under the License. */ -package org.apache.ignite.ci.tcmodel.mute; - -import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementWrapper; -import org.apache.ignite.ci.tcmodel.result.tests.TestRef; +package org.apache.ignite.ci.jira; /** - * Mute target (e.g. muted test). + * See example of GSON here + * https://issues.apache.org/jira/rest/api/2/issue/IGNITE-123 */ -@XmlAccessorType(XmlAccessType.FIELD) -public class MuteTarget { - /** Tests. */ - @XmlElementWrapper(name="tests") - @XmlElement(name="test") - public List<TestRef> tests; -} +public class Ticket { + /** Id. */ + public long id; + + /** Ticket full name like "IGNITE-123". */ + public String key; + + /** Fields. */ + public Fields fields; + + /** + * @return Ignite id (like 123 in IGNITE-123). + */ + public int igniteId() { + return Integer.valueOf(key.substring("IGNITE-".length())); + } + + /** + * @return Ticket status (open, resolved, etc); + */ + public String status() { + return fields.status.name; + } +} \ No newline at end of file diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteAssignment.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Tickets.java similarity index 50% copy from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteAssignment.java copy to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Tickets.java index 0c1c3ff..f265b37 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteAssignment.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Tickets.java @@ -15,40 +15,44 @@ * limitations under the License. */ -package org.apache.ignite.ci.tcmodel.mute; +package org.apache.ignite.ci.jira; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import org.apache.ignite.ci.util.TimeUtil; +import java.util.Collection; +import java.util.Collections; /** - * + * See example of GSON here + * https://issues.apache.org/jira/rest/api/2/search?jql=project%20=%20IGNITE%20order%20by%20updated%20DESC&fields=status */ -@XmlRootElement(name = "assignment") -public class MuteAssignment { - /** Mute date. */ - @XmlElement(name = "timestamp") public String muteDate; +public class Tickets { + /** Start at. */ + public int startAt; + + /** Max amount of tickets on the page. */ + public int maxResults; - /** Timestamp. */ - private long ts; + /** Total tickets. */ + public int total; - /** Mute comment. */ - @XmlElement public String text; + /** Jira tickets. */ + public Collection<Ticket> issues; /** - * @return Timestamp for mute date. + * @return Start index for next page. Return -1 if it is last page. */ - public long timestamp() { - if (ts == 0) - ts = TimeUtil.tcSimpleDateToTimestamp(muteDate); + public int nextStart() { + int next = startAt + maxResults; + + if (next < total) + return next; - return ts; + return -1; } /** - * @param ts Timestamp for mute date. + * @return Jira tickets. */ - public void timestamp(long ts) { - this.ts = ts; + public Collection<Ticket> issuesNotNull() { + return issues == null ? Collections.emptyList() : issues; } -} +} \ No newline at end of file diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/mute/MuteDao.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraTicketDao.java similarity index 50% copy from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/mute/MuteDao.java copy to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraTicketDao.java index a955701..4a6e414 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/mute/MuteDao.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraTicketDao.java @@ -15,13 +15,13 @@ * limitations under the License. */ -package org.apache.ignite.ci.teamcity.ignited.mute; +package org.apache.ignite.ci.jira.ignited; import com.google.common.base.Preconditions; +import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; import javax.cache.Cache; import javax.inject.Inject; import javax.inject.Provider; @@ -29,7 +29,7 @@ import org.apache.ignite.Ignite; import org.apache.ignite.IgniteCache; import org.apache.ignite.ci.db.TcHelperDb; import org.apache.ignite.ci.di.AutoProfiling; -import org.apache.ignite.ci.tcmodel.mute.MuteInfo; +import org.apache.ignite.ci.jira.Ticket; import org.apache.ignite.ci.teamcity.ignited.IStringCompactor; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.internal.U; @@ -37,15 +37,15 @@ import org.apache.ignite.internal.util.typedef.internal.U; /** * */ -public class MuteDao { +public class JiraTicketDao { /** Cache name. */ - public static final String TEAMCITY_MUTE_CACHE_NAME = "teamcityMute"; + public static final String TEAMCITY_JIRA_TICKET_CACHE_NAME = "jiraTickets"; /** Ignite provider. */ @Inject private Provider<Ignite> igniteProvider; /** Builds cache. */ - private IgniteCache<Long, MuteInfoCompacted> muteCache; + private IgniteCache<Long, TicketCompacted> jiraCache; /** Compactor. */ @Inject private IStringCompactor compactor; @@ -54,23 +54,22 @@ public class MuteDao { * */ public void init() { - muteCache = igniteProvider.get().getOrCreateCache(TcHelperDb.getCacheV2Config(TEAMCITY_MUTE_CACHE_NAME)); + jiraCache = igniteProvider.get().getOrCreateCache(TcHelperDb.getCache8PartsConfig(TEAMCITY_JIRA_TICKET_CACHE_NAME)); } /** * @param srvIdMaskHigh Server id mask high. - * @return Server mutes. + * @return Jira tickets. */ - @AutoProfiling - public SortedSet<MuteInfo> getMutes(long srvIdMaskHigh) { - Preconditions.checkNotNull(muteCache, "init() was not called"); - long srvId = srvIdMaskHigh << 32; + public Set<Ticket> getTickets(int srvIdMaskHigh) { + Preconditions.checkNotNull(jiraCache, "init() was not called"); + long srvId = (long) srvIdMaskHigh << 32; - TreeSet<MuteInfo> res = new TreeSet<>(); + Set<Ticket> res = new HashSet<>(); - for (Cache.Entry<Long, MuteInfoCompacted> entry : muteCache) { + for (Cache.Entry<Long, TicketCompacted> entry : jiraCache) { if ((entry.getKey() & srvId) == srvId) - res.add(entry.getValue().toMuteInfo(compactor)); + res.add(entry.getValue().toTicket(compactor)); } return res; @@ -80,11 +79,11 @@ public class MuteDao { * Combine server and project into key for storage. * * @param srvIdMaskHigh Server id mask high. - * @param muteId Mute id. + * @param igniteId Ticket. * @return Key from server-project pair. */ - public static long muteIdToCacheKey(int srvIdMaskHigh, int muteId) { - return (long) muteId | (long) srvIdMaskHigh << 32; + public static long ticketToCacheKey(int srvIdMaskHigh, int igniteId) { + return (long) igniteId | (long) srvIdMaskHigh << 32; } /** @@ -94,50 +93,21 @@ public class MuteDao { * @param chunk Chunk. */ @AutoProfiling - public void saveChunk(int srvIdMaskHigh, Set<MuteInfo> chunk) { - Preconditions.checkNotNull(muteCache, "init() was not called"); + public void saveChunk(int srvIdMaskHigh, Collection<Ticket> chunk) { + Preconditions.checkNotNull(jiraCache, "init() was not called"); if (F.isEmpty(chunk)) return; - HashMap<Long, MuteInfoCompacted> compactedMutes = new HashMap<>(U.capacity(chunk.size())); - - for (MuteInfo mute : chunk) { - long key = muteIdToCacheKey(srvIdMaskHigh, mute.id); - MuteInfoCompacted val = new MuteInfoCompacted(mute, compactor); - - compactedMutes.put(key, val); - } - - muteCache.putAll(compactedMutes); - } - - /** - * @param srvIdMaskHigh Server id mask high. - * @param muteId Mute id. - */ - public boolean remove(int srvIdMaskHigh, int muteId) { - return muteCache.remove(muteIdToCacheKey(srvIdMaskHigh, muteId)); - } - - /** - * @param srvIdMaskHigh Server id mask high. - * @param startId Start id. - */ - public int removeAllAfter(int srvIdMaskHigh, int startId) { - int rmv = 0; - long srvId = (long) srvIdMaskHigh << 32; + HashMap<Long, TicketCompacted> compactedTickets = new HashMap<>(U.capacity(chunk.size())); - for (Cache.Entry<Long, MuteInfoCompacted> entry : muteCache) { - if ((srvId & entry.getKey()) != srvId) - continue; + for (Ticket ticket : chunk) { + long key = ticketToCacheKey(srvIdMaskHigh, ticket.igniteId()); + TicketCompacted val = new TicketCompacted(ticket, compactor); - if (entry.getValue().id > startId) { - if (muteCache.remove(entry.getKey())) - rmv++; - } + compactedTickets.put(key, val); } - return rmv; + jiraCache.putAll(compactedTickets); } } 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 new file mode 100644 index 0000000..c5dabbc --- /dev/null +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraTicketSync.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ci.jira.ignited; + +import java.util.Collection; +import java.util.concurrent.TimeUnit; +import javax.inject.Inject; +import org.apache.ignite.ci.di.MonitoredTask; +import org.apache.ignite.ci.di.scheduler.IScheduler; +import org.apache.ignite.ci.jira.IJiraIntegration; +import org.apache.ignite.ci.jira.IJiraIntegrationProvider; +import org.apache.ignite.ci.jira.Ticket; +import org.apache.ignite.ci.jira.Tickets; +import org.apache.ignite.ci.teamcity.pure.ITeamcityConn; +import org.apache.ignite.ci.user.ICredentialsProv; +import org.apache.ignite.internal.util.typedef.F; + +/** + * + */ +public class JiraTicketSync { + /** Scheduler. */ + @Inject private IScheduler scheduler; + + /** Mute DAO. */ + @Inject private JiraTicketDao jiraDao; + + /** Jira integration provider. */ + @Inject IJiraIntegrationProvider jiraIntegrationProvider; + + /** + * @param taskName Task name. + * @param srvIdMaskHigh Server id mask high. + * @param creds Credentials. + * @param conn Connection. + */ + public void ensureActualizeJiraTickets(String taskName, int srvIdMaskHigh, ICredentialsProv creds, ITeamcityConn conn) { + scheduler.sheduleNamed(taskName, () -> actualizeJiraTickets(srvIdMaskHigh, conn, creds), 15, TimeUnit.MINUTES); + } + + /** + * @param srvIdMaskHigh Server id mask high. + * @param conn Connection. + * @param creds Credentials. + */ + @MonitoredTask(name = "Actualize Jira", nameExtArgsIndexes = {0}) + private String actualizeJiraTickets(int srvIdMaskHigh, ITeamcityConn conn, ICredentialsProv creds) { + String srvId = conn.serverId(); + IJiraIntegration jira = jiraIntegrationProvider.server(srvId); + String url = "search?jql=project%20=%20IGNITE%20order%20by%20updated%20DESC&fields=status&maxResults=100"; + Tickets tickets = jira.getTickets(srvId, creds, url); + Collection<Ticket> page = tickets.issuesNotNull(); + + if (F.isEmpty(page)) + return "Something went wrong - no tickets found. Check jira availability."; + + jiraDao.saveChunk(srvIdMaskHigh, page); + + int ticketsSaved = page.size(); + + while (tickets.nextStart() > 0) { + url = "search?jql=project%20=%20IGNITE%20order%20by%20updated%20DESC&fields=status&maxResults=100&startAt=" + + tickets.nextStart(); + + tickets = jira.getTickets(srvId, creds, url); + + page = tickets.issuesNotNull(); + + if (F.isEmpty(page)) + break; + + jiraDao.saveChunk(srvIdMaskHigh, page); + + ticketsSaved += page.size(); + } + + return "Jira tickets saved " + ticketsSaved + " for " + srvId; + } +} diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/TicketCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/TicketCompacted.java new file mode 100644 index 0000000..8989994 --- /dev/null +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/TicketCompacted.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.ci.jira.ignited; + +import org.apache.ignite.ci.jira.Fields; +import org.apache.ignite.ci.jira.Status; +import org.apache.ignite.ci.jira.Ticket; +import org.apache.ignite.ci.teamcity.ignited.IStringCompactor; + +/** + * + */ +public class TicketCompacted { + /** Id. */ + public long id; + + /** Ticket full name like "IGNITE-123". */ + public int igniteId; + + /** Fields. */ + public int status; + + /** + * @param ticket Jira ticket. + * @param comp Compactor. + */ + public TicketCompacted(Ticket ticket, IStringCompactor comp) { + id = ticket.id; + igniteId = Integer.valueOf(ticket.key.substring("IGNITE-".length())); + status = comp.getStringId(ticket.fields.status.name); + } + + /** + * @param comp Compactor. + */ + public Ticket toTicket(IStringCompactor comp) { + Ticket ticket = new Ticket(); + + ticket.id = id; + ticket.key = "IGNITE-" + igniteId; + ticket.fields = new Fields(); + ticket.fields.status = new Status(comp.getStringFromId(status)); + + return ticket; + } +} 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 e45b353..aecc4d1 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 @@ -182,7 +182,7 @@ public class TcBotTriggerAndSignOffService { public Set<MuteInfo> getMutes(String srvId, String projectId, ICredentialsProv creds) { ITeamcityIgnited ignited = teamcityIgnitedProvider.server(srvId, creds); - Set<MuteInfo> infos = ignited.getMutes(projectId); + Set<MuteInfo> infos = ignited.getMutes(projectId, creds); for (MuteInfo info : infos) info.assignment.muteDate = THREAD_FORMATTER.get().format(new Date(info.assignment.timestamp())); diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteAssignment.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteAssignment.java index 0c1c3ff..d70f894 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteAssignment.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteAssignment.java @@ -22,7 +22,7 @@ import javax.xml.bind.annotation.XmlRootElement; import org.apache.ignite.ci.util.TimeUtil; /** - * + * Mute additional information. Contains mute date and it's comment. */ @XmlRootElement(name = "assignment") public class MuteAssignment { diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteInfo.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteInfo.java index 87925f8..61a153b 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteInfo.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteInfo.java @@ -26,7 +26,10 @@ import javax.xml.bind.annotation.XmlRootElement; import org.jetbrains.annotations.NotNull; /** - * + * TeamCity mute. + * <p> + * See example of XML here + * https://ci.ignite.apache.org/app/rest/mutes/ */ @XmlRootElement(name = "mute") @XmlAccessorType(XmlAccessType.FIELD) @@ -43,6 +46,9 @@ public class MuteInfo implements Comparable<MuteInfo> { /** Target. */ @XmlElement public MuteTarget target; + /** Jira ticket status. TeamCity don't send it, we fill it when send mutes.html. */ + @XmlElement public String ticketStatus; + /** {@inheritDoc} */ @Override public boolean equals(Object o) { if (this == o) diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteScope.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteScope.java index ac2ae28..e2137d6 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteScope.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteScope.java @@ -26,7 +26,7 @@ import org.apache.ignite.ci.tcmodel.conf.BuildType; import org.apache.ignite.ci.tcmodel.conf.Project; /** - * + * Mute additional information. Contains project or build types - scope affected by mute. */ @XmlAccessorType(XmlAccessType.FIELD) public class MuteScope { diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteTarget.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteTarget.java index 2d437de..cd52735 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteTarget.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/MuteTarget.java @@ -25,7 +25,7 @@ import javax.xml.bind.annotation.XmlElementWrapper; import org.apache.ignite.ci.tcmodel.result.tests.TestRef; /** - * Mute target (e.g. muted test). + * Mute additional information. Contains what was muted (tests, problems). */ @XmlAccessorType(XmlAccessType.FIELD) public class MuteTarget { diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/Mutes.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/Mutes.java index 9b7fe40..c8177b4 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/Mutes.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/mute/Mutes.java @@ -31,9 +31,8 @@ import org.apache.ignite.ci.tcmodel.result.AbstractRef; /** * Mute entities from TeamCity. On TeamCity this object represent page with several mutes. * <p> - * But we unite mutes into single object to store in mute cache. - * <p> - * See https://ci.ignite.apache.org/app/rest/mutes/ + * See example of XML here + * https://ci.ignite.apache.org/app/rest/mutes/ */ @XmlRootElement(name = "mutes") @XmlAccessorType(XmlAccessType.FIELD) 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 36a54e9..ead6dd7 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 @@ -30,6 +30,7 @@ import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeCompacted; import org.apache.ignite.ci.teamcity.ignited.buildtype.BuildTypeRefCompacted; import org.apache.ignite.ci.teamcity.ignited.change.ChangeCompacted; import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted; +import org.apache.ignite.ci.user.ICredentialsProv; import org.jetbrains.annotations.NotNull; /** @@ -59,9 +60,10 @@ public interface ITeamcityIgnited { /** * @param projectId Project id. + * @param creds Credentials. * @return Mutes for associated server and given project pair. */ - Set<MuteInfo> getMutes(String projectId); + public Set<MuteInfo> getMutes(String projectId, ICredentialsProv creds); /** * Return all builds for branch and suite with finish status. 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 d305d5b..4a4e19f 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 @@ -27,6 +27,9 @@ import org.apache.ignite.ci.di.AutoProfiling; import org.apache.ignite.ci.di.MonitoredTask; import org.apache.ignite.ci.di.cache.GuavaCached; import org.apache.ignite.ci.di.scheduler.IScheduler; +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.mute.MuteInfo; import org.apache.ignite.ci.teamcity.ignited.mute.MuteDao; @@ -50,6 +53,8 @@ import org.apache.ignite.ci.teamcity.ignited.fatbuild.ProactiveFatBuildSync; import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistCompactedDao; import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync; import org.apache.ignite.ci.teamcity.pure.ITeamcityConn; +import org.apache.ignite.ci.user.ICredentialsProv; +import org.apache.ignite.internal.util.typedef.F; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -108,6 +113,12 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited { /** Mute Sync. */ @Inject private MuteSync muteSync; + /** Jira ticket DAO. */ + @Inject private JiraTicketDao jiraTicketDao; + + /** Jira ticket Sync. */ + @Inject private JiraTicketSync jiraTicketSync; + /** Changes DAO. */ @Inject private ChangeDao changesDao; @@ -146,6 +157,7 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited { changesDao.init(); runHistCompactedDao.init(); muteDao.init(); + jiraTicketDao.init(); } /** @@ -326,10 +338,45 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited { } /** {@inheritDoc} */ - @Override public Set<MuteInfo> getMutes(String projectId) { + @Override public Set<MuteInfo> getMutes(String projectId, ICredentialsProv creds) { muteSync.ensureActualizeMutes(taskName("actualizeMutes"), projectId, srvIdMaskHigh, conn); + jiraTicketSync.ensureActualizeJiraTickets(taskName("actualizeJiraTickets"), srvIdMaskHigh, creds, conn); + + SortedSet<MuteInfo> mutes = muteDao.getMutes(srvIdMaskHigh); + Collection<Ticket> tickets = jiraTicketDao.getTickets(srvIdMaskHigh); - return muteDao.getMutes(srvIdMaskHigh); + insertTicketStatus(mutes, tickets); + + return mutes; + } + + /** + * Insert ticket status for all mutes, if they have ticket in description. + * + * @param mutes Mutes. + * @param tickets Tickets. + */ + private void insertTicketStatus(SortedSet<MuteInfo> mutes, Collection<Ticket> tickets) { + for (MuteInfo mute : mutes) { + if (F.isEmpty(mute.assignment.text)) + continue; + + int pos = mute.assignment.text.indexOf("https://issues.apache.org/jira/browse/"); + + if (pos == -1) + continue; + + for (Ticket ticket : tickets) { + String muteTicket = mute.assignment.text.substring(pos + + "https://issues.apache.org/jira/browse/".length()); + + if (ticket.key.equals(muteTicket)) { + mute.ticketStatus = ticket.status(); + + break; + } + } + } } /** {@inheritDoc} */ diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java index a6d76f2..1dd0fe5 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedModule.java @@ -18,6 +18,8 @@ package org.apache.ignite.ci.teamcity.ignited; import com.google.inject.AbstractModule; import com.google.inject.internal.SingletonScope; +import org.apache.ignite.ci.jira.ignited.JiraTicketDao; +import org.apache.ignite.ci.jira.ignited.JiraTicketSync; import org.apache.ignite.ci.teamcity.ignited.buildcondition.BuildConditionDao; import org.apache.ignite.ci.teamcity.ignited.buildref.BuildRefDao; import org.apache.ignite.ci.teamcity.ignited.buildref.BuildRefSync; @@ -29,6 +31,7 @@ import org.apache.ignite.ci.teamcity.ignited.change.ChangeSync; import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildDao; import org.apache.ignite.ci.teamcity.ignited.fatbuild.ProactiveFatBuildSync; import org.apache.ignite.ci.teamcity.ignited.mute.MuteDao; +import org.apache.ignite.ci.teamcity.ignited.mute.MuteSync; import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistCompactedDao; import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync; import org.apache.ignite.ci.teamcity.pure.ITeamcityHttpConnection; @@ -58,6 +61,9 @@ public class TeamcityIgnitedModule extends AbstractModule { bind(RunHistCompactedDao.class).in(new SingletonScope()); bind(RunHistSync.class).in(new SingletonScope()); bind(MuteDao.class).in(new SingletonScope()); + bind(MuteSync.class).in(new SingletonScope()); + bind(JiraTicketDao.class).in(new SingletonScope()); + bind(JiraTicketSync.class).in(new SingletonScope()); bind(IStringCompactor.class).to(IgniteStringCompactor.class).in(new SingletonScope()); diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/mute/MuteDao.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/mute/MuteDao.java index a955701..7dfb017 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/mute/MuteDao.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/mute/MuteDao.java @@ -62,9 +62,9 @@ public class MuteDao { * @return Server mutes. */ @AutoProfiling - public SortedSet<MuteInfo> getMutes(long srvIdMaskHigh) { + public SortedSet<MuteInfo> getMutes(int srvIdMaskHigh) { Preconditions.checkNotNull(muteCache, "init() was not called"); - long srvId = srvIdMaskHigh << 32; + long srvId = (long) srvIdMaskHigh << 32; TreeSet<MuteInfo> res = new TreeSet<>(); diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/mute/MuteSync.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/mute/MuteSync.java index 53f5a57..8c40542 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/mute/MuteSync.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/mute/MuteSync.java @@ -48,6 +48,8 @@ public class MuteSync { * Refresh mutes for given project. * * @param projectId Project id. + * @param srvIdMaskHigh Server id mask high. + * @param conn TeamCity connection. * @return Message with loading result. */ @MonitoredTask(name = "Actualize Mute", nameExtArgsIndexes = {0}) diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/HttpUtil.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/HttpUtil.java index 817fa04..2418189 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/HttpUtil.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/util/HttpUtil.java @@ -228,7 +228,7 @@ public class HttpUtil { } /** - * Send POST request to the GitHub url. + * Send POST request to the JIRA url. * * @param jiraAuthTok Authorization Base64 token. * @param url URL. @@ -257,7 +257,37 @@ public class HttpUtil { logger.info("\nSending 'POST' request to URL : " + url + "\n" + body); - try (InputStream inputStream = getInputStream(con)){ + try (InputStream inputStream = getInputStream(con)) { + return readIsToString(inputStream); + } + } + + /** + * Send GET request to the JIRA url. + * + * @param jiraAuthTok Jira auth token. + * @param url Url. + */ + public static String sendGetToJira(String jiraAuthTok, String url) throws IOException { + Stopwatch started = Stopwatch.createStarted(); + URL obj = new URL(url); + HttpURLConnection con = (HttpURLConnection)obj.openConnection(); + Charset charset = StandardCharsets.UTF_8; + + con.setRequestProperty("accept-charset", charset.toString()); + con.setRequestProperty("Authorization", "Basic " + jiraAuthTok); + con.setRequestProperty("content-type", "application/json"); + con.setRequestProperty("Connection", "Keep-Alive"); + con.setRequestProperty("Keep-Alive", "header"); + + con.setRequestMethod("GET"); + + int resCode = con.getResponseCode(); + + logger.info(Thread.currentThread().getName() + ": Required: " + started.elapsed(TimeUnit.MILLISECONDS) + + "ms : Sending 'GET' request to : " + url + " Response: " + resCode); + + try (InputStream inputStream = getInputStream(con)) { return readIsToString(inputStream); } } diff --git a/ignite-tc-helper-web/src/main/webapp/mutes.html b/ignite-tc-helper-web/src/main/webapp/mutes.html index b714b8c..ee8e767 100644 --- a/ignite-tc-helper-web/src/main/webapp/mutes.html +++ b/ignite-tc-helper-web/src/main/webapp/mutes.html @@ -54,30 +54,30 @@ $.ajax({ url: "rest/tracked/mutes?serverId=apache", success: function (result) { - showVisasTable(result); + showTable(result); }, error: showErrInLoadStatus } ); } - function showVisasTable(result) { + function showTable(result) { // Debug info // if (isDefinedAndFilled(result)) { // result.sort((a, b) => (a.id < b.id) ? -1 : ((a.id > b.id) ? 1 : 0)); // console.log(result); // } - let visasTable = $('#visasTable'); + let table = $('#table'); let testNameMatcher = new RegExp("\\.(\\w+\\d*):.*\\.([a-z][$\\w]+\\w+\\d*)"); let testNameMatcher2 = new RegExp("(\\w+\.Test\\w+\\d*)$"); let suiteNameMatcher2 = new RegExp("(.*):"); let ticketMatcher = new RegExp("https:\\/\\/issues.apache.org\\/jira\\/browse\\/(IGNITE-\\d+)"); - visasTable.dataTable().fnDestroy(); + table.dataTable().fnDestroy(); - visasTable.DataTable({ + table.DataTable({ data: result, "iDisplayLength": 30, //rows to be shown by default stateSave: true, @@ -167,6 +167,13 @@ } }, { + title: "Status", + width: 50, + "data": function (data, type, row, meta) { + return data.ticketStatus; + } + }, + { title: "Mute Date", "data": function (data, type, row, meta) { return data.assignment.timestamp; @@ -195,7 +202,7 @@ <br> <div id="loadStatus"></div> <br> -<table id="visasTable" class="row-border" style="width:100%"> +<table id="table" class="row-border" style="width:100%"> <thead> <tr class="ui-widget-header "> <th>.</th> @@ -204,6 +211,7 @@ <th>.</th> <th>.</th> <th>.</th> + <th>.</th> </tr> </thead> </table>
