You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by dp...@apache.org on 2019/02/02 18:19:08 UTC
[ignite-teamcity-bot] branch master updated: IGNITE-11105 Supported
Teamcity servers aliases - Fixes #111.
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 aee540e IGNITE-11105 Supported Teamcity servers aliases - Fixes #111.
aee540e is described below
commit aee540ec6ce9882051b2f9b77a967637c5341bd1
Author: Dmitriy Pavlov <dp...@apache.org>
AuthorDate: Sat Feb 2 21:18:55 2019 +0300
IGNITE-11105 Supported Teamcity servers aliases - Fixes #111.
Signed-off-by: Dmitriy Pavlov <dp...@apache.org>
---
conf/branches.json | 6 +
.../java/org/apache/ignite/ci/HelperConfig.java | 45 +--
.../apache/ignite/ci/IgnitePersistentTeamcity.java | 17 --
.../apache/ignite/ci/IgniteTeamcityConnection.java | 49 ++--
.../org/apache/ignite/ci/analysis/RunStat.java | 7 -
.../org/apache/ignite/ci/conf/PasswordEncoder.java | 10 +-
.../org/apache/ignite/ci/di/cache/GuavaCached.java | 2 +
.../ignite/ci/di/cache/GuavaCachedInterceptor.java | 8 +-
.../ci/github/ignited/GitHubConnIgnitedImpl.java | 11 +
.../ci/github/ignited/IGitHubConnIgnited.java | 17 +-
.../ci/github/pure/GitHubConnectionImpl.java | 25 +-
.../ignite/ci/github/pure/IGitHubConnection.java | 16 +-
.../java/org/apache/ignite/ci/jira/Tickets.java | 1 +
.../ignite/ci/jira/ignited/IJiraIgnited.java | 17 +-
.../apache/ignite/ci/jira/ignited/JiraIgnited.java | 20 +-
.../ignite/ci/jira/ignited/JiraTicketDao.java | 18 +-
.../ignite/ci/jira/ignited/JiraTicketSync.java | 24 +-
.../ignite/ci/jira/ignited/TicketCompacted.java | 43 ++-
.../apache/ignite/ci/jira/{ => pure}/Fields.java | 14 +-
.../ignite/ci/jira/pure/IJiraIntegration.java | 24 +-
.../java/org/apache/ignite/ci/jira/pure/Jira.java | 86 +++---
.../apache/ignite/ci/jira/{ => pure}/Status.java | 4 +-
.../apache/ignite/ci/jira/{ => pure}/Ticket.java | 9 +-
.../org/apache/ignite/ci/jobs/CheckQueueJob.java | 24 +-
.../ignite/ci/tcbot/chain/PrChainsProcessor.java | 5 +-
.../ci/tcbot/common/StringFieldCompacted.java | 160 +++++++++++
.../ci/{ => tcbot}/conf/BranchesTracked.java | 52 +++-
.../apache/ignite/ci/tcbot/conf/GitHubConfig.java | 83 ++++++
.../Fields.java => tcbot/conf/IGitHubConfig.java} | 20 +-
.../{ITcBotConfig.java => IJiraServerConfig.java} | 40 ++-
.../apache/ignite/ci/tcbot/conf/ITcBotConfig.java | 12 +-
.../conf/ITcServerConfig.java} | 27 +-
.../ignite/ci/tcbot/conf/JiraServerConfig.java | 144 ++++++++++
.../ci/tcbot/conf/LocalFilesBasedConfig.java | 54 +++-
.../ignite/ci/tcbot/conf/TcServerConfig.java | 102 +++++++
.../ignite/ci/tcbot/visa/BranchTicketMatcher.java | 302 +++++++++++++++++++++
.../tcbot/visa/TcBotTriggerAndSignOffService.java | 228 ++++------------
.../ci/teamcity/ignited/ITeamcityIgnited.java | 3 -
.../teamcity/ignited/ITeamcityIgnitedProvider.java | 8 +
.../teamcity/ignited/TcIgnitedCachingProvider.java | 32 ++-
.../ci/teamcity/ignited/TeamcityIgnitedImpl.java | 5 -
.../teamcity/ignited/fatbuild/TestCompacted.java | 29 +-
.../ignite/ci/teamcity/pure/ITeamcityConn.java | 40 ++-
.../model/current/ChainAtServerCurrentStatus.java | 32 +--
.../ignite/ci/web/model/current/UpdateInfo.java | 2 +-
.../org/apache/ignite/ci/web/rest/GetBuildLog.java | 3 +-
.../ignite/ci/web/rest/GetTrackedBranches.java | 27 +-
.../apache/ignite/ci/web/rest/TriggerBuilds.java | 2 +-
.../exception/ServiceUnauthorizedException.java | 4 +-
.../org/apache/ignite/ci/web/rest/login/Login.java | 7 +-
.../ignite/ci/web/rest/pr/GetPrTestFailures.java | 3 +-
.../rest/tracked/GetTrackedBranchTestResults.java | 3 +-
.../ignite/ci/web/rest/visa/TcBotVisaService.java | 19 +-
ignite-tc-helper-web/src/main/webapp/js/prs-1.1.js | 2 +-
ignite-tc-helper-web/src/main/webapp/prs.html | 13 +-
.../ci/tcbot/chain/MockBasedTcBotModule.java | 35 ++-
.../ci/tcbot/chain/TrackedBranchProcessorTest.java | 2 +-
.../ignite/ci/tcbot/issue/IssueDetectorTest.java | 2 +-
.../ci/teamcity/ignited/TeamcityIgnitedMock.java | 2 +-
.../ignited/TeamcityIgnitedProviderMock.java | 11 +-
60 files changed, 1421 insertions(+), 591 deletions(-)
diff --git a/conf/branches.json b/conf/branches.json
index 0b0d9bf..05087a4 100644
--- a/conf/branches.json
+++ b/conf/branches.json
@@ -1,4 +1,10 @@
{
+ "primaryServerCode": "apache",
+ "tcServers": [
+ ],
+ "jiraServers": [
+ {}
+ ],
"branches": [
{
"id": "master",
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 ebdb919..b1e4c85 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
@@ -25,8 +25,8 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Properties;
-import javax.ws.rs.QueryParam;
-import org.apache.ignite.ci.conf.BranchesTracked;
+
+import org.apache.ignite.ci.tcbot.conf.BranchesTracked;
import org.apache.ignite.ci.conf.PasswordEncoder;
import org.apache.ignite.ci.tcbot.TcBotSystemProperties;
import org.apache.ignite.ci.util.Base64Util;
@@ -45,8 +45,6 @@ public class HelperConfig {
public static final String MAIL_PROPS = "mail.auth.properties";
public static final String HOST = "host";
public static final String USERNAME = "username";
- @Deprecated
- private static final String PASSWORD = "password";
public static final String ENCODED_PASSWORD = "encoded_password";
/** GitHub authorization token property name. */
@@ -61,13 +59,11 @@ public class HelperConfig {
/** JIRA authorization token property name. */
public static final String GIT_API_URL = "git.api_url";
- /** JIRA authorization token property name. */
- public static final String JIRA_API_URL = "jira.api_url";
-
/** JIRA URL to build links to tickets. */
public static final String JIRA_URL = "jira.url";
/** Prefix for JIRA ticket names. */
+ @Deprecated
public static final String JIRA_TICKET_TEMPLATE = "jira.ticket_template";
/** Slack authorization token property name. */
@@ -94,7 +90,7 @@ public class HelperConfig {
writer.write(USERNAME + "=" + ENDL);
writer.write(ENCODED_PASSWORD + "=" + ENDL);
}
- throw new IllegalStateException("Please setup username and encodedPassword in config file [" +
+ throw new IllegalStateException("Please setup parameters for service in config file [" +
file.getCanonicalPath() + "]");
}
return loadProps(file);
@@ -178,26 +174,19 @@ public class HelperConfig {
* Extract TeamCity authorization token from properties.
*
* @param props Properties, where token is placed.
- * @param configName Configuration name.
+ * @param cfgName Configuration name.
* @return Null or decoded auth token for Github.
*/
- @Nullable static String prepareBasicHttpAuthToken(Properties props, String configName) {
- final String user = getMandatoryProperty(props, USERNAME, configName);
- String pwd = props.getProperty(PASSWORD);
- boolean filled = !isNullOrEmpty(pwd);
+ @Nullable static String prepareBasicHttpAuthToken(Properties props, String cfgName) {
+ final String user = getMandatoryProperty(props, USERNAME, cfgName);
- if (!filled) {
- String enc = props.getProperty(ENCODED_PASSWORD);
+ String enc = props.getProperty(ENCODED_PASSWORD);
- if(!isNullOrEmpty(enc)) {
- pwd = PasswordEncoder.decode(enc);
- filled = true;
- }
- }
-
- if (!filled)
+ if (isNullOrEmpty(enc))
return null;
+ String pwd = PasswordEncoder.decode(enc);
+
return userPwdToToken(user, pwd);
}
@@ -205,9 +194,9 @@ public class HelperConfig {
return Base64Util.encodeUtf8String(user + ":" + pwd);
}
- public static String getMandatoryProperty(Properties props, String key, String configName) {
+ public static String getMandatoryProperty(Properties props, String key, String cfgName) {
final String user = props.getProperty(key);
- Preconditions.checkState(!isNullOrEmpty(user), key + " property should be filled in " + configName);
+ Preconditions.checkState(!isNullOrEmpty(user), key + " property should be filled in " + cfgName);
return user;
}
@@ -235,14 +224,6 @@ public class HelperConfig {
}
}
-
- @NotNull public static File getLogsDirForServer(@QueryParam("serverId") String serverId) {
- final File workDir = resolveWorkDir();
- final String configName = prepareConfigName(serverId);
- final Properties props = loadAuthProperties(workDir, configName);
- return resolveLogs(workDir, props);
- }
-
@NotNull static File resolveLogs(File workDir, Properties props) {
final String logsProp = props.getProperty(LOGS, "logs");
final File logsDirFileConfigured = new File(logsProp);
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 3d53e45..b40f24a 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
@@ -79,10 +79,6 @@ public class IgnitePersistentTeamcity implements IAnalyticsEnabledTeamcity, ITea
@Nullable
private String serverId;
- //todo: remove triggering dependency from getTrackedBranch processing, use TC Bot DB data.
- @Deprecated
- private static long lastTriggerMs = System.currentTimeMillis();
-
@Override public void init(ITeamcity conn) {
this.teamcity = conn;
this.serverId = conn.serverId();
@@ -125,12 +121,6 @@ public class IgnitePersistentTeamcity implements IAnalyticsEnabledTeamcity, ITea
return serverId;
}
- public static int getTriggerRelCacheValidSecs(int defaultSecs) {
- long msSinceTrigger = System.currentTimeMillis() - lastTriggerMs;
- long secondsSinceTrigger = TimeUnit.MILLISECONDS.toSeconds(msSinceTrigger);
- return Math.min((int) secondsSinceTrigger, defaultSecs);
- }
-
@NotNull private String ignCacheNme(String cache) {
return ignCacheNme(cache, serverId);
}
@@ -226,8 +216,6 @@ public class IgnitePersistentTeamcity implements IAnalyticsEnabledTeamcity, ITea
/** {@inheritDoc} */
@AutoProfiling
@Override public Build triggerBuild(String buildTypeId, @NotNull String branchName, boolean cleanRebuild, boolean queueAtTop) {
- lastTriggerMs = System.currentTimeMillis();
-
return teamcity.triggerBuild(buildTypeId, branchName, cleanRebuild, queueAtTop);
}
@@ -241,11 +229,6 @@ public class IgnitePersistentTeamcity implements IAnalyticsEnabledTeamcity, ITea
return teamcity.getProjects();
}
- /** {@inheritDoc} */
- @Override public String gitBranchPrefix() {
- return teamcity.gitBranchPrefix();
- }
-
@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 c667d66..241d5d0 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
@@ -27,6 +27,8 @@ import org.apache.ignite.ci.analysis.LogCheckTask;
import org.apache.ignite.ci.analysis.SingleBuildRunCtx;
import org.apache.ignite.ci.di.AutoProfiling;
import org.apache.ignite.ci.logs.BuildLogStreamChecker;
+import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
+import org.apache.ignite.ci.tcbot.conf.ITcServerConfig;
import org.apache.ignite.ci.tcmodel.agent.Agent;
import org.apache.ignite.ci.tcmodel.agent.AgentsRef;
import org.apache.ignite.ci.tcmodel.changes.Change;
@@ -99,44 +101,35 @@ public class IgniteTeamcityConnection implements ITeamcity {
/** Teamcity http connection. */
@Inject private ITeamcityHttpConnection teamcityHttpConn;
+ @Inject private ITcBotConfig config;
- private String configName; //main properties file name
private String tcName;
/** Build logger processing running. */
private ConcurrentHashMap<Integer, CompletableFuture<LogCheckTask>> buildLogProcessingRunning = new ConcurrentHashMap<>();
- /** Git branch prefix for seach TC runs in PR-less contributions. */
- @NotNull
- private String gitBranchPrefix;
-
public Executor getExecutor() {
return executor;
}
/** {@inheritDoc} */
- public void init(@Nullable String tcName) {
+ @Override public void init(@Nullable String tcName) {
this.tcName = tcName;
- final File workDir = HelperConfig.resolveWorkDir();
- this.configName = HelperConfig.prepareConfigName(tcName);
+ ITcServerConfig tcCfg = this.config.getTeamcityConfig(tcName);
+ final Properties props = tcCfg.properties();
- final Properties props = HelperConfig.loadAuthProperties(workDir, configName);
- final String hostConf = props.getProperty(HelperConfig.HOST, "https://ci.ignite.apache.org/");
-
- this.host = hostConf.trim() + (hostConf.endsWith("/") ? "" : "/");
+ this.host = tcCfg.host();
try {
if (!Strings.isNullOrEmpty(props.getProperty(HelperConfig.USERNAME))
&& props.getProperty(HelperConfig.ENCODED_PASSWORD) != null)
- setAuthToken(HelperConfig.prepareBasicHttpAuthToken(props, configName));
+ setAuthToken(HelperConfig.prepareBasicHttpAuthToken(props, "TC Config"));
} catch (Exception e) {
e.printStackTrace();
logger.error("Failed to set credentials", e);
}
-
- this.gitBranchPrefix = props.getProperty(HelperConfig.GIT_BRANCH_PREFIX, "ignite-");
-
+ final File workDir = HelperConfig.resolveWorkDir();
final File logsDirFile = HelperConfig.resolveLogs(workDir, props);
logsDir = ensureDirExist(logsDirFile);
@@ -154,7 +147,6 @@ public class IgniteTeamcityConnection implements ITeamcity {
return basicAuthTok != null;
}
-
/** {@inheritDoc} */
@AutoProfiling
@Override public List<Agent> agents(boolean connected, boolean authorized) {
@@ -181,7 +173,7 @@ public class IgniteTeamcityConnection implements ITeamcity {
return file;
}
- String url = host + "downloadBuildLog.html" + "?buildId=" + buildIdStr + "&archived=true";
+ String url = host() + "downloadBuildLog.html" + "?buildId=" + buildIdStr + "&archived=true";
try {
HttpUtil.sendGetCopyToFile(basicAuthTok, url, file);
@@ -249,7 +241,7 @@ public class IgniteTeamcityConnection implements ITeamcity {
" </properties>\n" +
"</build>";
- String url = host + "app/rest/buildQueue";
+ String url = host() + "app/rest/buildQueue";
try {
logger.info("Triggering build: buildTypeId={}, branchName={}, cleanRebuild={}, queueAtTop={}",
@@ -321,17 +313,12 @@ public class IgniteTeamcityConnection implements ITeamcity {
/** {@inheritDoc} */
@Override public List<Project> getProjects() {
- return sendGetXmlParseJaxb(host + "app/rest/latest/projects", ProjectsList.class).projects();
- }
-
- /** {@inheritDoc} */
- @Override public String gitBranchPrefix() {
- return gitBranchPrefix;
+ return sendGetXmlParseJaxb(host() + "app/rest/latest/projects", ProjectsList.class).projects();
}
/** {@inheritDoc} */
@Override public List<BuildType> getBuildTypes(String projectId) {
- return sendGetXmlParseJaxb(host + "app/rest/latest/projects/" + projectId, Project.class)
+ return sendGetXmlParseJaxb(host() + "app/rest/latest/projects/" + projectId, Project.class)
.getBuildTypesNonNull();
}
@@ -360,7 +347,7 @@ public class IgniteTeamcityConnection implements ITeamcity {
/** {@inheritDoc} */
@AutoProfiling
@Override public BuildTypeFull getBuildType(String buildTypeId) {
- return sendGetXmlParseJaxb(host + "app/rest/latest/buildTypes/id:" +
+ return sendGetXmlParseJaxb(host() + "app/rest/latest/buildTypes/id:" +
buildTypeId, BuildTypeFull.class);
}
@@ -375,7 +362,7 @@ public class IgniteTeamcityConnection implements ITeamcity {
* @param elem Element class.
*/
private <T> T getJaxbUsingHref(String href, Class<T> elem) {
- return sendGetXmlParseJaxb(host + (href.startsWith("/") ? href.substring(1) : href), elem);
+ return sendGetXmlParseJaxb(host() + (href.startsWith("/") ? href.substring(1) : href), elem);
}
/** {@inheritDoc} */
@@ -451,7 +438,7 @@ public class IgniteTeamcityConnection implements ITeamcity {
@Override public List<BuildRef> getBuildRefsPage(String fullUrl, AtomicReference<String> outNextPage) {
String relPath = "app/rest/latest/builds?locator=defaultFilter:false";
String relPathSelected = Strings.isNullOrEmpty(fullUrl) ? relPath : fullUrl;
- String url = host + (relPathSelected.startsWith("/") ? relPathSelected.substring(1) : relPathSelected);
+ String url = host() + (relPathSelected.startsWith("/") ? relPathSelected.substring(1) : relPathSelected);
Builds builds = sendGetXmlParseJaxb(url, Builds.class);
outNextPage.set(Strings.emptyToNull(builds.nextHref()));
@@ -463,7 +450,7 @@ public class IgniteTeamcityConnection implements ITeamcity {
@Override public SortedSet<MuteInfo> getMutesPage(String buildTypeId, String fullUrl, AtomicReference<String> nextPage) {
String relPath = "app/rest/mutes?locator=project:(id:" + buildTypeId + ')';
String relPathSelected = Strings.isNullOrEmpty(fullUrl) ? relPath : fullUrl;
- String url = host + (relPathSelected.startsWith("/") ? relPathSelected.substring(1) : relPathSelected);
+ String url = host() + (relPathSelected.startsWith("/") ? relPathSelected.substring(1) : relPathSelected);
Mutes mutes = sendGetXmlParseJaxb(url, Mutes.class);
@@ -476,7 +463,7 @@ public class IgniteTeamcityConnection implements ITeamcity {
@AutoProfiling
@Override public TestOccurrencesFull getTestsPage(int buildId, @Nullable String href, boolean testDtls) {
String relPathSelected = Strings.isNullOrEmpty(href) ? testsStartHref(buildId, testDtls) : href;
- String url = host + (relPathSelected.startsWith("/") ? relPathSelected.substring(1) : relPathSelected);
+ String url = host() + (relPathSelected.startsWith("/") ? relPathSelected.substring(1) : relPathSelected);
return sendGetXmlParseJaxb(url, TestOccurrencesFull.class);
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/RunStat.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/RunStat.java
index ed035eb..60187e6 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/RunStat.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/RunStat.java
@@ -73,13 +73,6 @@ public class RunStat implements IRunHistory {
this.name = name;
}
- private ChangesState changesStatus(Boolean changesExist) {
- if (changesExist == null)
- return ChangesState.UNKNOWN;
-
- return changesExist ? ChangesState.EXIST : ChangesState.NONE;
- }
-
public void addTestRunToLatest(TestOccurrence testOccurrence, ChangesState changesState) {
TestId id = extractFullId(testOccurrence.getId());
if (id == null) {
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 97788d9..c1769b1 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
@@ -89,7 +89,7 @@ public class PasswordEncoder {
return parseHexBinary(Strings.padStart(Integer.toHexString(length), 2, '0'));
}
- public static void main(String[] args) {
+ public static void main0(String[] args) {
String pass = "324aadfe23....";
String encode = encode(pass);
System.err.println("Encoded: " + HelperConfig.GITHUB_AUTH_TOKEN + "=" + encode);
@@ -105,8 +105,12 @@ public class PasswordEncoder {
Preconditions.checkState(decode.equals(pass));
}
- public static void main3(String[] args) {
- String tok = HelperConfig.userPwdToToken("ignitetcbot", "222");
+ public static void main(String[] args) {
+ encodeJiraTok("ignitetcbot", "21313");
+ }
+
+ public static void encodeJiraTok(String user, String pwd) {
+ String tok = HelperConfig.userPwdToToken(user, pwd);
String encode = encode(tok);
System.err.println("Encoded: " + HelperConfig.JIRA_AUTH_TOKEN + "=" + encode);
String decode = decode(encode);
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/cache/GuavaCached.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/cache/GuavaCached.java
index 628d3fe..4913f60 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/cache/GuavaCached.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/cache/GuavaCached.java
@@ -45,4 +45,6 @@ public @interface GuavaCached {
boolean cacheNegativeNumbersRval() default true;
long expireAfterAccessSecs() default -1;
+
+ long expireAfterWriteSecs() default -1;
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/cache/GuavaCachedInterceptor.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/cache/GuavaCachedInterceptor.java
index adca7fc..5acac88 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/cache/GuavaCachedInterceptor.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/di/cache/GuavaCachedInterceptor.java
@@ -45,12 +45,16 @@ public class GuavaCachedInterceptor implements MethodInterceptor {
if(annotation.softValues())
builder = builder.softValues();
- if(annotation.maximumSize()>0)
+ if(annotation.maximumSize() > 0)
builder = builder.maximumSize(annotation.maximumSize());
- if(annotation.expireAfterAccessSecs()>0)
+ if (annotation.expireAfterAccessSecs() > 0)
builder.expireAfterAccess(annotation.expireAfterAccessSecs(), TimeUnit.SECONDS);
+ if (annotation.expireAfterWriteSecs() > 0)
+ builder.expireAfterWrite(annotation.expireAfterWriteSecs(), TimeUnit.SECONDS);
+
+
return builder.build();
});
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 dcbf1f4..769cb3e 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.apache.ignite.ci.tcbot.conf.IGitHubConfig;
import org.jetbrains.annotations.NotNull;
/**
@@ -85,6 +86,16 @@ class GitHubConnIgnitedImpl implements IGitHubConnIgnited {
}
/** {@inheritDoc} */
+ @Override public String gitBranchPrefix() {
+ return config().gitBranchPrefix();
+ }
+ /** {@inheritDoc} */
+ @Override
+ public IGitHubConfig config() {
+ return conn.config();
+ }
+
+ /** {@inheritDoc} */
@AutoProfiling
@Override public List<PullRequest> getPullRequests() {
scheduler.sheduleNamed(taskName("actualizePrs"), this::actualizePrs, 2, TimeUnit.MINUTES);
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 c61619b..ae405f8 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
@@ -16,17 +16,17 @@
*/
package org.apache.ignite.ci.github.ignited;
-import com.google.common.base.Preconditions;
import java.util.List;
-import javax.annotation.Nullable;
-import org.apache.ignite.ci.di.AutoProfiling;
import org.apache.ignite.ci.github.PullRequest;
-import org.apache.ignite.ci.github.pure.IGitHubConnection;
+import org.apache.ignite.ci.tcbot.conf.IGitHubConfig;
+import org.apache.ignite.ci.tcbot.conf.IJiraServerConfig;
/**
*
*/
public interface IGitHubConnIgnited {
+ IGitHubConfig config();
+
/**
* @return list of open pull requests
*/
@@ -40,7 +40,12 @@ public interface IGitHubConnIgnited {
*
* @param url Url.
* @param body Request body.
- * @return {@code True} - if GitHub was notified. {@code False} - otherwise.
*/
- void notifyGit(String url, String body);
+ public void notifyGit(String url, String body);
+
+ /**
+ * Prefix to be added to git branch instead of {@link IJiraServerConfig#branchNumPrefix()}.
+ * Usually it is a lower case of JIRA branch mention, e.. JIRA branch num is 'IGNITE-', and git is 'ignite-'
+ */
+ public String gitBranchPrefix();
}
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 f3f177c..da392dc 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
@@ -34,11 +34,15 @@ import java.util.concurrent.atomic.AtomicReference;
import org.apache.ignite.ci.HelperConfig;
import org.apache.ignite.ci.di.AutoProfiling;
import org.apache.ignite.ci.github.PullRequest;
+import org.apache.ignite.ci.tcbot.conf.IGitHubConfig;
+import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
import org.apache.ignite.ci.util.HttpUtil;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.inject.Inject;
+
import static com.google.common.base.Strings.isNullOrEmpty;
class GitHubConnectionImpl implements IGitHubConnection {
@@ -51,6 +55,11 @@ class GitHubConnectionImpl implements IGitHubConnection {
/** GitHub authorization token. */
private String gitAuthTok;
+ @Inject
+ ITcBotConfig config;
+
+ private String srvCode;
+
@Nullable public static String parseNextLinkFromLinkRspHeader(String s) {
String nextLink = null;
StringTokenizer tokenizer = new StringTokenizer(s, ",");
@@ -81,15 +90,18 @@ class GitHubConnectionImpl implements IGitHubConnection {
}
/** {@inheritDoc} */
- @Override public void init(String srvId) {
+ @Override
+ public void init(String srvCode) {
+ this.srvCode = srvCode;
final File workDir = HelperConfig.resolveWorkDir();
- String cfgName = HelperConfig.prepareConfigName(srvId);
+ String cfgName = HelperConfig.prepareConfigName(srvCode);
final Properties props = HelperConfig.loadAuthProperties(workDir, cfgName);
- gitAuthTok = (HelperConfig.prepareGithubHttpAuthToken(props));
- gitApiUrl = (props.getProperty(HelperConfig.GIT_API_URL));
+ gitAuthTok = HelperConfig.prepareGithubHttpAuthToken(props);
+ gitApiUrl = props.getProperty(HelperConfig.GIT_API_URL);
+
}
/** {@inheritDoc} */
@@ -171,4 +183,9 @@ class GitHubConnectionImpl implements IGitHubConnection {
throw new UncheckedIOException(e);
}
}
+
+ /** {@inheritDoc} */
+ @Override public IGitHubConfig config() {
+ return config.getGitConfig(srvCode);
+ }
}
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 b2ab22a..733c057 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
@@ -19,14 +19,17 @@ package org.apache.ignite.ci.github.pure;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
+
+import com.google.common.base.Strings;
import org.apache.ignite.ci.github.PullRequest;
+import org.apache.ignite.ci.tcbot.conf.IGitHubConfig;
import org.jetbrains.annotations.Nullable;
/**
*
*/
public interface IGitHubConnection {
- void init(String srvId);
+ void init(String srvCode);
/** */
PullRequest getPullRequest(Integer id);
@@ -55,7 +58,7 @@ public interface IGitHubConnection {
/**
* @return PR id from string "pull/XXXX/head"
*/
- @Nullable public static Integer convertBranchToId(String branchForTc) {
+ @Nullable public static Integer convertBranchToPrId(String branchForTc) {
Integer res = null;
if (Objects.isNull(branchForTc))
@@ -73,11 +76,8 @@ public interface IGitHubConnection {
}
}
- try {
- res = Integer.parseInt(id);
- }
- finally {
- return res;
- }
+ return Strings.isNullOrEmpty(id) ? null : Integer.parseInt(id);
}
+
+ IGitHubConfig config();
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Tickets.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Tickets.java
index 930a1bf..a6e3758 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Tickets.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Tickets.java
@@ -19,6 +19,7 @@ package org.apache.ignite.ci.jira;
import java.util.Collection;
import java.util.Collections;
+import org.apache.ignite.ci.jira.pure.Ticket;
/**
* See example of GSON here
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/IJiraIgnited.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/IJiraIgnited.java
index be1011a..6288d43 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/IJiraIgnited.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/IJiraIgnited.java
@@ -18,25 +18,14 @@ package org.apache.ignite.ci.jira.ignited;
import java.io.IOException;
import java.util.Set;
-import org.apache.ignite.ci.jira.Ticket;
-import org.jetbrains.annotations.NotNull;
+import org.apache.ignite.ci.jira.pure.Ticket;
+import org.apache.ignite.ci.tcbot.conf.IJiraServerConfig;
/**
*
*/
public interface IJiraIgnited {
/**
- *
- */
- @NotNull public String ticketPrefix();
-
- /**
- *
- */
- @NotNull public String projectName();
-
-
- /**
* @return Jira tickets.
*/
public Set<Ticket> getTickets();
@@ -62,4 +51,6 @@ public interface IJiraIgnited {
* @throws IllegalStateException If can't find URL to the JIRA.
*/
public String postJiraComment(String ticket, String comment) throws IOException;
+
+ public IJiraServerConfig config();
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraIgnited.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraIgnited.java
index 1ffe5ec..fd3d7b9 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraIgnited.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraIgnited.java
@@ -19,10 +19,10 @@ package org.apache.ignite.ci.jira.ignited;
import java.io.IOException;
import java.util.Set;
import javax.inject.Inject;
-import org.apache.ignite.ci.jira.Ticket;
+import org.apache.ignite.ci.jira.pure.Ticket;
import org.apache.ignite.ci.jira.pure.IJiraIntegration;
+import org.apache.ignite.ci.tcbot.conf.IJiraServerConfig;
import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
-import org.jetbrains.annotations.NotNull;
/**
*
@@ -56,21 +56,12 @@ class JiraIgnited implements IJiraIgnited {
jiraTicketDao.init();
}
- /** {@inheritDoc} */
- @Override public String ticketPrefix() {
- return jira.ticketPrefix();
- }
-
- /** {@inheritDoc} */
- @NotNull @Override public String projectName() {
- return jira.projectName();
- }
/** {@inheritDoc} */
@Override public Set<Ticket> getTickets() {
jiraTicketSync.ensureActualizeJiraTickets(srvId);
- return jiraTicketDao.getTickets(srvIdMaskHigh, ticketPrefix());
+ return jiraTicketDao.getTickets(srvIdMaskHigh, jira.config().projectCodeForVisa());
}
/** {@inheritDoc} */
@@ -87,4 +78,9 @@ class JiraIgnited implements IJiraIgnited {
@Override public String postJiraComment(String ticket, String comment) throws IOException {
return jira.postJiraComment(ticket, comment);
}
+
+ /** {@inheritDoc} */
+ @Override public IJiraServerConfig config() {
+ return jira.config();
+ }
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraTicketDao.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraTicketDao.java
index 30def78..2250e38 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraTicketDao.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/ignited/JiraTicketDao.java
@@ -30,7 +30,8 @@ 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.jira.Ticket;
+import org.apache.ignite.ci.di.cache.GuavaCached;
+import org.apache.ignite.ci.jira.pure.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;
@@ -60,10 +61,11 @@ public class JiraTicketDao {
/**
* @param srvIdMaskHigh Server id mask high.
- * @param ticketPrefix Fixed prefix for JIRA tickets.
+ * @param projectCode project code. WIth delim gives Fixed prefix for JIRA tickets.
* @return Jira tickets.
*/
- public Set<Ticket> getTickets(int srvIdMaskHigh, String ticketPrefix) {
+ @GuavaCached(expireAfterWriteSecs = 60, softValues = true)
+ public Set<Ticket> getTickets(int srvIdMaskHigh, String projectCode) {
Preconditions.checkNotNull(jiraCache, "init() was not called");
long srvId = (long) srvIdMaskHigh << 32;
@@ -71,7 +73,7 @@ public class JiraTicketDao {
for (Cache.Entry<Long, TicketCompacted> entry : jiraCache) {
if ((entry.getKey() & srvId) == srvId)
- res.add(entry.getValue().toTicket(compactor, ticketPrefix));
+ res.add(entry.getValue().toTicket(compactor, projectCode));
}
return res;
@@ -92,11 +94,11 @@ public class JiraTicketDao {
* Save small part of loaded mutes.
* @param srvIdMaskHigh Server id mask high.
* @param chunk Chunk.
- * @param ticketPrefix Ticket name template.
+ * @param projectCode Project code for contributions listing and for comments.
* @return number of tickets totally saved.
*/
@AutoProfiling
- public int saveChunk(int srvIdMaskHigh, Collection<Ticket> chunk, String ticketPrefix) {
+ public int saveChunk(int srvIdMaskHigh, Collection<Ticket> chunk, String projectCode) {
Preconditions.checkNotNull(jiraCache, "init() was not called");
if (F.isEmpty(chunk))
@@ -105,8 +107,8 @@ public class JiraTicketDao {
Map<Long, TicketCompacted> compactedTickets = new HashMap<>(U.capacity(chunk.size()));
for (Ticket ticket : chunk) {
- long key = ticketToCacheKey(srvIdMaskHigh, ticket.igniteId(ticketPrefix));
- TicketCompacted val = new TicketCompacted(ticket, compactor, ticketPrefix);
+ long key = ticketToCacheKey(srvIdMaskHigh, ticket.keyWithoutProject(projectCode));
+ TicketCompacted val = new TicketCompacted(ticket, compactor, projectCode);
compactedTickets.put(key, val);
}
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 0b97084..dca8033 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
@@ -17,15 +17,19 @@
package org.apache.ignite.ci.jira.ignited;
+import java.lang.reflect.Field;
+import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
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.Tickets;
+import org.apache.ignite.ci.jira.pure.Fields;
import org.apache.ignite.ci.jira.pure.IJiraIntegration;
import org.apache.ignite.ci.jira.pure.IJiraIntegrationProvider;
-import org.apache.ignite.ci.jira.Ticket;
-import org.apache.ignite.ci.jira.Tickets;
+import org.apache.ignite.ci.jira.pure.Ticket;
import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
import org.apache.ignite.internal.util.typedef.F;
import org.jetbrains.annotations.NotNull;
@@ -86,9 +90,15 @@ public class JiraTicketSync {
int srvIdMaskHigh = ITeamcityIgnited.serverIdToInt(srvId);
IJiraIntegration jira = jiraIntegrationProvider.server(srvId);
- String projectName = jira.projectName();
- String baseUrl = "search?jql=" + escape("project=" + projectName + " order by updated DESC")
- + "&fields=status&maxResults=100";
+ String reqFields = Arrays.stream(Fields.class.getDeclaredFields())
+ .map(Field::getName)
+ .collect(Collectors.joining(","));
+
+ String projectCode = jira.config().projectCodeForVisa();
+ String baseUrl = "search?jql=" + escape("project=" + projectCode + " order by updated DESC")
+ + "&" +
+ "fields=" + reqFields +
+ "&maxResults=100";
String url = baseUrl;
Tickets tickets = jira.getTicketsPage(url);
@@ -97,7 +107,7 @@ public class JiraTicketSync {
if (F.isEmpty(page))
return "Something went wrong - no tickets found. Check jira availability.";
- int ticketsSaved = jiraDao.saveChunk(srvIdMaskHigh, page, jira.ticketPrefix());
+ int ticketsSaved = jiraDao.saveChunk(srvIdMaskHigh, page, projectCode);
int ticketsProcessed = page.size();
@@ -112,7 +122,7 @@ public class JiraTicketSync {
if (F.isEmpty(page))
break;
- int savedNow = jiraDao.saveChunk(srvIdMaskHigh, page, jira.ticketPrefix());
+ int savedNow = jiraDao.saveChunk(srvIdMaskHigh, page, projectCode);
ticketsSaved += savedNow;
ticketsProcessed += page.size();
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
index 4eb942e..f009a8f 100644
--- 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
@@ -18,15 +18,18 @@
package org.apache.ignite.ci.jira.ignited;
import com.google.common.base.Objects;
-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.jira.pure.Fields;
+import org.apache.ignite.ci.jira.pure.Status;
+import org.apache.ignite.ci.jira.pure.Ticket;
+import org.apache.ignite.ci.tcbot.common.StringFieldCompacted;
import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
+import org.jetbrains.annotations.Nullable;
/**
*
*/
public class TicketCompacted {
+ public static final String PROJECT_DELIM = "-";
/** Id. */
public long id;
@@ -36,28 +39,43 @@ public class TicketCompacted {
/** Id of string: Fields/status/name, value compacted. */
public int status;
+ /** Summary, nullable because of older entries. */
+ @Nullable private StringFieldCompacted summary = new StringFieldCompacted();
+
+ /** Custom field, to be queriable after persisting in Ignite, nullable because of older entry versions. */
+ @Nullable private StringFieldCompacted customfield_11050 = new StringFieldCompacted();
+
+ /** Full description, nullable because of older entry versions. */
+ @Nullable private StringFieldCompacted description = new StringFieldCompacted();
+
/**
* @param ticket Jira ticket.
* @param comp Compactor.
- * @param ticketTemplate Ticket name template.
+ * @param projectCode project name for commenting jira.
*/
- public TicketCompacted(Ticket ticket, IStringCompactor comp, String ticketTemplate) {
+ public TicketCompacted(Ticket ticket, IStringCompactor comp, String projectCode) {
id = ticket.id;
- igniteId = Integer.valueOf(ticket.key.substring(ticketTemplate.length()));
+ igniteId = ticket.keyWithoutProject(projectCode);
status = comp.getStringId(ticket.fields.status.name);
+ summary.setValue(ticket.fields.summary);
+ customfield_11050.setValue(ticket.fields.customfield_11050);
+ description.setValue(ticket.fields.description);
}
/**
* @param comp Compactor.
- * @param ticketPrefix Ticket name fixed prefix for the project.
+ * @param projectCode project code for VISA and filtering tasks.
*/
- public Ticket toTicket(IStringCompactor comp, String ticketPrefix) {
+ public Ticket toTicket(IStringCompactor comp, String projectCode) {
Ticket ticket = new Ticket();
ticket.id = id;
- ticket.key = ticketPrefix + igniteId;
+ ticket.key = projectCode + PROJECT_DELIM + igniteId;
ticket.fields = new Fields();
ticket.fields.status = new Status(comp.getStringFromId(status));
+ ticket.fields.summary = summary != null ? summary.getValue() : null;
+ ticket.fields.customfield_11050 = customfield_11050 != null ? customfield_11050.getValue() : null;
+ ticket.fields.description = description != null ? description.getValue() : null;
return ticket;
}
@@ -74,11 +92,14 @@ public class TicketCompacted {
return id == compacted.id &&
igniteId == compacted.igniteId &&
- status == compacted.status;
+ status == compacted.status &&
+ Objects.equal(summary, compacted.summary) &&
+ Objects.equal(customfield_11050, compacted.customfield_11050) &&
+ Objects.equal(description, compacted.description);
}
/** {@inheritDoc} */
@Override public int hashCode() {
- return Objects.hashCode(id, igniteId, status);
+ return Objects.hashCode(id, igniteId, status, summary, customfield_11050, description);
}
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Fields.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/Fields.java
similarity index 78%
copy from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Fields.java
copy to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/Fields.java
index 2f6e271..02ed0b2 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Fields.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/Fields.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.ignite.ci.jira;
+package org.apache.ignite.ci.jira.pure;
import com.google.common.base.MoreObjects;
@@ -26,10 +26,20 @@ public class Fields {
/** Ticket status. */
public Status status;
- /** {@inheritDoc} */
+ /** Summary. */
+ public String summary;
+
+ /** Customfield 11050. */
+ public String customfield_11050;
+
+ /** Description. */
+ public String description;
+
@Override public String toString() {
return MoreObjects.toStringHelper(this)
.add("status", status)
+ .add("summary", summary)
+ .add("customfield_11050", customfield_11050)
.toString();
}
}
\ No newline at end of file
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/IJiraIntegration.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/IJiraIntegration.java
index 9410350..210478f 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/IJiraIntegration.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/IJiraIntegration.java
@@ -19,6 +19,7 @@ package org.apache.ignite.ci.jira.pure;
import java.io.IOException;
import org.apache.ignite.ci.jira.Tickets;
+import org.apache.ignite.ci.tcbot.conf.IJiraServerConfig;
import org.jetbrains.annotations.NotNull;
/**
@@ -26,16 +27,6 @@ import org.jetbrains.annotations.NotNull;
*/
public interface IJiraIntegration {
- /** @return JIRA ticket prefix. */
- @NotNull public String ticketPrefix();
-
- /**
- *
- */
- @NotNull public default String projectName() {
- return ticketPrefix().replaceAll("-", "");
- }
-
/**
* @return Internal identified service ID.
*/
@@ -58,14 +49,11 @@ public interface IJiraIntegration {
/**
* Produce wrapper for collection of Jira tickets for given server.
*
- * @param url Tickets loading URL and parameters.
+ * @param url Tickets loading URL and parameters, URL is relative, should not contain any start slashes.
* @return Jira tickets.
*/
public Tickets getTicketsPage(String url);
- /** */
- public String jiraUrl();
-
/**
* @param ticketFullName Ticket full name (e.g IGNITE-8331)
* @return URL which is used as link to Jira ticket with specified name.
@@ -78,10 +66,8 @@ public interface IJiraIntegration {
*/
public String generateCommentUrl(String ticketFullName, int commentId);
- String getJiraApiUrl();
+ String restApiUrl();
- /**
- * @return {@code True} if JIRA authorization token is available.
- */
- boolean isJiraTokenAvailable();
+
+ public IJiraServerConfig config();
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/Jira.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/Jira.java
index c11cfcc..f43ea72 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/Jira.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/Jira.java
@@ -18,15 +18,15 @@
package org.apache.ignite.ci.jira.pure;
import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
import com.google.gson.Gson;
-import java.io.File;
import java.io.IOException;
-import java.util.Properties;
-import org.apache.ignite.ci.HelperConfig;
+import javax.inject.Inject;
import org.apache.ignite.ci.di.AutoProfiling;
import org.apache.ignite.ci.jira.Tickets;
+import org.apache.ignite.ci.tcbot.conf.IJiraServerConfig;
+import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
import org.apache.ignite.ci.util.HttpUtil;
+import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -40,46 +40,16 @@ class Jira implements IJiraIntegration {
/** Logger. */
private static final Logger logger = LoggerFactory.getLogger(Jira.class);
- /** */
- private String jiraUrl;
-
- /** JIRA ticket prefix. */
- @NotNull private String jiraTicketPrefix;
-
- /** JIRA authorization token. */
- private String jiraBasicAuthTok;
-
- /** URL for JIRA integration. */
- private String jiraApiUrl;
-
/** Server id. */
private String srvId;
+ /** Config. */
+ @Inject ITcBotConfig cfg;
+
/** {@inheritDoc} */
@Override public void init(String srvId) {
this.srvId = srvId;
- final File workDir = HelperConfig.resolveWorkDir();
-
- final String cfgName = HelperConfig.prepareConfigName(srvId);
-
- final Properties props = HelperConfig.loadAuthProperties(workDir, cfgName);
-
- jiraUrl = props.getProperty(HelperConfig.JIRA_URL);
- jiraTicketPrefix = props.getProperty(HelperConfig.JIRA_TICKET_TEMPLATE, "IGNITE-");
-
- jiraBasicAuthTok = HelperConfig.prepareJiraHttpAuthToken(props);
- jiraApiUrl = props.getProperty(HelperConfig.JIRA_API_URL);
- }
-
- /** {@inheritDoc} */
- @Override public String jiraUrl() {
- return jiraUrl;
- }
-
- /** {@inheritDoc} */
- @Override public String ticketPrefix() {
- return jiraTicketPrefix;
}
/** {@inheritDoc} */
@@ -99,6 +69,8 @@ class Jira implements IJiraIntegration {
/** {@inheritDoc} */
@Override public String generateTicketUrl(String ticketFullName) {
+ @Nullable String jiraUrl = config().getUrl();
+
Preconditions.checkState(!isNullOrEmpty(jiraUrl), "Jira URL is not configured for this server.");
return jiraUrl + "browse/" + ticketFullName;
@@ -113,38 +85,48 @@ class Jira implements IJiraIntegration {
}
/** {@inheritDoc} */
- @Override public String getJiraApiUrl() {
- return jiraApiUrl;
+ @Override public IJiraServerConfig config() {
+ return cfg.getJiraConfig(srvId);
}
/** {@inheritDoc} */
- @Override public boolean isJiraTokenAvailable() {
- return !Strings.isNullOrEmpty(jiraBasicAuthTok);
+ @AutoProfiling
+ @Override public String postJiraComment(String ticket, String comment) throws IOException {
+ String jiraApiUrl = restApiUrl();
+
+ String url = jiraApiUrl + "issue/" + ticket + "/comment";
+
+ return HttpUtil.sendPostAsStringToJira(config().decodedHttpAuthToken(), url, "{\"body\": \"" + comment + "\"}");
}
/** {@inheritDoc} */
- @AutoProfiling
- @Override public String postJiraComment(String ticket, String comment) throws IOException {
- if (isNullOrEmpty(jiraApiUrl))
+ @Override @NotNull public String restApiUrl() {
+ String jiraUrl = config().getUrl();
+
+ if (isNullOrEmpty(jiraUrl))
throw new IllegalStateException("JIRA API URL is not configured for this server.");
- String url = jiraApiUrl + "issue/" + ticket + "/comment";
+ StringBuilder apiUrl = new StringBuilder();
+
+ apiUrl.append(jiraUrl);
+ if (!jiraUrl.endsWith("/"))
+ apiUrl.append("/");
+
+ apiUrl.append("rest/api/2/");
- return HttpUtil.sendPostAsStringToJira(jiraBasicAuthTok, url, "{\"body\": \"" + comment + "\"}");
+ return apiUrl.toString();
}
/**
- * @param url Url.
+ * @param url Url, relative, should not contain any start slashes.
* @return Response as gson string.
*/
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);
+ return HttpUtil.sendGetToJira(config().decodedHttpAuthToken(), restApiUrl() + url);
}
- public String getServiceId() {
+ /** {@inheritDoc} */
+ @Override public String getServiceId() {
return srvId;
}
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Status.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/Status.java
similarity index 94%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Status.java
rename to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/Status.java
index 94d2131..1821c5f 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Status.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/Status.java
@@ -15,9 +15,7 @@
* limitations under the License.
*/
-package org.apache.ignite.ci.jira;
-
-import com.google.common.base.MoreObjects;
+package org.apache.ignite.ci.jira.pure;
/**
* Status for Jira ticket.
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Ticket.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/Ticket.java
similarity index 86%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Ticket.java
rename to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/Ticket.java
index dc8806f..4d5c514 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Ticket.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/pure/Ticket.java
@@ -15,9 +15,10 @@
* limitations under the License.
*/
-package org.apache.ignite.ci.jira;
+package org.apache.ignite.ci.jira.pure;
import com.google.common.base.MoreObjects;
+import org.apache.ignite.ci.jira.ignited.TicketCompacted;
/**
* See example of GSON here
@@ -34,10 +35,12 @@ public class Ticket {
public Fields fields;
/**
- * @param ticketPrefix Ticket name fixed prefix.
+ * @param projectCode JIRA project code to be removed from ticket key.
* @return Ignite ticket Number ignoring project code (like 123 in IGNITE-123).
*/
- public int igniteId(String ticketPrefix) {
+ public int keyWithoutProject(String projectCode) {
+ String ticketPrefix = projectCode + TicketCompacted.PROJECT_DELIM;
+
return Integer.valueOf(key.substring(ticketPrefix.length()));
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jobs/CheckQueueJob.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jobs/CheckQueueJob.java
index 0b54c5b..41bd9f4 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jobs/CheckQueueJob.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jobs/CheckQueueJob.java
@@ -17,12 +17,21 @@
package org.apache.ignite.ci.jobs;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import javax.inject.Inject;
import jersey.repackaged.com.google.common.base.Throwables;
-import org.apache.ignite.ci.HelperConfig;
import org.apache.ignite.ci.conf.BranchTracked;
import org.apache.ignite.ci.conf.ChainAtServerTracked;
import org.apache.ignite.ci.di.AutoProfiling;
import org.apache.ignite.ci.di.MonitoredTask;
+import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
import org.apache.ignite.ci.tcmodel.agent.Agent;
import org.apache.ignite.ci.tcmodel.result.Build;
import org.apache.ignite.ci.tcmodel.result.Triggered;
@@ -36,12 +45,6 @@ import org.apache.ignite.ci.user.ICredentialsProv;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.inject.Inject;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
/**
* Trigger build if half of agents are available and there is no self-triggered builds in build queue.
*/
@@ -66,6 +69,9 @@ public class CheckQueueJob implements Runnable {
@Inject private IStringCompactor compactor;
/** */
+ @Inject private ITcBotConfig cfg;
+
+ /** */
private final Map<ChainAtServerTracked, Long> startTimes = new HashMap<>();
/**
@@ -92,13 +98,13 @@ public class CheckQueueJob implements Runnable {
@AutoProfiling
@MonitoredTask(name = "Check Queue")
protected String runEx() {
- if (Boolean.valueOf(System.getProperty(CheckQueueJob.AUTO_TRIGGERING_BUILD_DISABLED))) {
+ if (Boolean.valueOf(System.getProperty(AUTO_TRIGGERING_BUILD_DISABLED))) {
final String msg = "Automatic build triggering was disabled.";
logger.info(msg);
return msg;
}
- List<BranchTracked> tracked = HelperConfig.getTrackedBranches().getBranches();
+ List<BranchTracked> tracked = cfg.getTrackedBranches().getBranches();
if (tracked == null || tracked.isEmpty()) {
final String msg = "Background check queue skipped - no config set for tracked branches.";
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessor.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessor.java
index f94501e..adf2508 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessor.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/PrChainsProcessor.java
@@ -26,6 +26,7 @@ import org.apache.ignite.ci.github.ignited.IGitHubConnIgnited;
import org.apache.ignite.ci.github.ignited.IGitHubConnIgnitedProvider;
import org.apache.ignite.ci.jira.pure.IJiraIntegration;
import org.apache.ignite.ci.jira.pure.IJiraIntegrationProvider;
+import org.apache.ignite.ci.tcbot.visa.BranchTicketMatcher;
import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
@@ -72,6 +73,8 @@ public class PrChainsProcessor {
/** */
@Inject IJiraIntegrationProvider jiraIntegrationProvider;
+ @Inject private BranchTicketMatcher ticketMatcher;
+
/**
* @param creds Credentials.
* @param srvId Server id.
@@ -160,7 +163,7 @@ public class PrChainsProcessor {
//fail rate reference is always default (master)
chainStatus.initFromContext(tcIgnited, ctx, baseBranch);
- chainStatus.initJiraAndGitInfo(tcIgnited, jiraIntegration, gitHubConnIgnited);
+ chainStatus.initJiraAndGitInfo(ticketMatcher, jiraIntegration, gitHubConnIgnited);
}
res.addChainOnServer(chainStatus);
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/common/StringFieldCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/common/StringFieldCompacted.java
new file mode 100644
index 0000000..f5f9085
--- /dev/null
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/common/StringFieldCompacted.java
@@ -0,0 +1,160 @@
+/*
+ * 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.tcbot.common;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Strings;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xerial.snappy.Snappy;
+
+public class StringFieldCompacted {
+ /** Logger. */
+ private static final Logger logger = LoggerFactory.getLogger(StringFieldCompacted.class);
+ public static final int FLAG_UNCOMPRESSED = 0;
+ public static final int FLAG_SNAPPY = 1;
+ public static final int FLAG_GZIP = 2;
+ byte flag;
+ byte data[];
+
+ public String getValue() {
+ if (data == null)
+ return "";
+
+ if (flag == FLAG_SNAPPY) {
+ try {
+ return new String(Snappy.uncompress(data), StandardCharsets.UTF_8);
+ }
+ catch (IOException e) {
+ logger.error("Snappy.uncompress failed: " + e.getMessage(), e);
+ return null;
+ }
+ }
+ else if (flag == FLAG_UNCOMPRESSED)
+ return new String(data, StandardCharsets.UTF_8);
+ else if (flag == FLAG_GZIP) {
+ try {
+ return unzipToString(data);
+ }
+ catch (Exception e) {
+ logger.error("GZip.uncompress failed: " + e.getMessage(), e);
+ return null;
+ }
+ }
+ else
+ return null;
+ }
+
+ @NotNull public static String unzipToString(byte[] data) throws IOException {
+ final ByteArrayInputStream in = new ByteArrayInputStream(data);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ try (final GZIPInputStream gzi = new GZIPInputStream(in)) {
+ byte[] outbuf = new byte[data.length];
+ int len;
+ while ((len = gzi.read(outbuf, 0, outbuf.length)) != -1)
+ bos.write(outbuf, 0, len);
+ }
+
+ return new String(bos.toByteArray(), StandardCharsets.UTF_8);
+ }
+
+ public void setValue(String str) {
+ if (Strings.isNullOrEmpty(str)) {
+ this.data = null;
+ return;
+ }
+
+ byte[] uncompressed;
+ byte[] snappy = null;
+ byte[] gzip = null;
+ try {
+ uncompressed = str.getBytes(StandardCharsets.UTF_8);
+ }
+ catch (Exception e) {
+ logger.error("Set details failed: " + e.getMessage(), e);
+ return;
+ }
+
+ try {
+ snappy = Snappy.compress(uncompressed);
+ }
+ catch (Exception e) {
+ logger.error("Snappy.compress failed: " + e.getMessage(), e);
+ }
+
+ try {
+ gzip = zipBytes(uncompressed);
+ }
+ catch (Exception e) {
+ logger.error("Snappy.compress failed: " + e.getMessage(), e);
+ }
+
+ final int snappyLen = snappy != null ? snappy.length : -1;
+ final int gzipLen = gzip != null ? gzip.length : -1;
+
+ flag = FLAG_UNCOMPRESSED;
+ //uncompressed
+ data = uncompressed;
+
+ if (snappyLen > 0 && snappyLen < data.length) {
+ flag = FLAG_SNAPPY;
+ data = snappy;
+ }
+
+ if (gzipLen > 0 && gzipLen < data.length) {
+ flag = FLAG_GZIP;
+ data = gzip;
+ }
+
+ logger.info("U " + uncompressed.length + " S " + snappyLen + " Z " + gzipLen + ": F (" +
+ flag + ")");
+ }
+
+ public static byte[] zipBytes(byte[] uncompressed ) throws IOException {
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ try (final GZIPOutputStream gzipOutputStream = new GZIPOutputStream(out)) {
+ gzipOutputStream.write(uncompressed);
+ }
+
+ return out.toByteArray();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ StringFieldCompacted compacted = (StringFieldCompacted)o;
+ return flag == compacted.flag &&
+ Arrays.equals(data, compacted.data);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return Objects.hashCode(flag, data);
+ }
+}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/conf/BranchesTracked.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/BranchesTracked.java
similarity index 55%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/conf/BranchesTracked.java
rename to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/BranchesTracked.java
index 8dc92d0..3a30609 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/conf/BranchesTracked.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/BranchesTracked.java
@@ -15,10 +15,15 @@
* limitations under the License.
*/
-package org.apache.ignite.ci.conf;
+package org.apache.ignite.ci.tcbot.conf;
import java.util.*;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.annotation.Nullable;
+
+import org.apache.ignite.ci.conf.BranchTracked;
+import org.apache.ignite.ci.conf.ChainAtServer;
/**
* Config file for tracked branches.
@@ -27,6 +32,18 @@ public class BranchesTracked {
/** Branches. */
private List<BranchTracked> branches = new ArrayList<>();
+ /** Primary server ID. */
+ @Nullable private String primaryServerCode;
+
+ /** Additional list Servers to be used for validation of PRs, but not for tracking any branches. */
+ private List<TcServerConfig> tcServers = new ArrayList<>();
+
+ /** JIRA config to be used . */
+ private List<JiraServerConfig> jiraServers = new ArrayList<>();
+
+ /** JIRA config to be used . */
+ private List<GitHubConfig> gitHubConfigs = new ArrayList<>();
+
/**
* @return list of internal identifiers of branch.
*/
@@ -34,6 +51,9 @@ public class BranchesTracked {
return branches.stream().map(BranchTracked::getId).collect(Collectors.toList());
}
+ /**
+ * Get Unique suites involved into tracked branches
+ */
public Set<ChainAtServer> getSuitesUnique() {
return branches.stream()
.flatMap(BranchTracked::getChainsStream)
@@ -49,8 +69,17 @@ public class BranchesTracked {
return get(branch).orElseThrow(() -> new RuntimeException("Branch not found: " + branch));
}
+ /**
+ *
+ */
public Set<String> getServerIds() {
- return branches.stream().flatMap(BranchTracked::getChainsStream).map(ChainAtServer::getServerId).collect(Collectors.toSet());
+ Stream<String> srvsInTracked = branches.stream()
+ .flatMap(BranchTracked::getChainsStream)
+ .map(ChainAtServer::getServerId);
+
+ return Stream.concat(srvsInTracked,
+ tcServers.stream().map(TcServerConfig::getCode))
+ .collect(Collectors.toSet());
}
public List<BranchTracked> getBranches() {
@@ -60,4 +89,23 @@ public class BranchesTracked {
public void addBranch(BranchTracked branch) {
branches.add(branch);
}
+
+ /**
+ * @return Primary server code.
+ */
+ @Nullable public String primaryServerCode() {
+ return primaryServerCode;
+ }
+
+ Optional<TcServerConfig> getTcConfig(String code) {
+ return tcServers.stream().filter(s -> code.equals(s.getCode())).findAny();
+ }
+
+ Optional<JiraServerConfig> getJiraConfig(String code) {
+ return jiraServers.stream().filter(s -> code.equals(s.getCode())).findAny();
+ }
+
+ public Optional<GitHubConfig> getGitHubConfig(String code) {
+ return gitHubConfigs.stream().filter(s -> code.equals(s.getCode())).findAny();
+ }
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/GitHubConfig.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/GitHubConfig.java
new file mode 100644
index 0000000..9b21df3
--- /dev/null
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/GitHubConfig.java
@@ -0,0 +1,83 @@
+/*
+ * 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.tcbot.conf;
+
+import com.google.common.base.Strings;
+import org.apache.ignite.ci.HelperConfig;
+
+import java.util.Properties;
+
+/**
+ *
+ */
+public class GitHubConfig implements IGitHubConfig {
+ public static final String DEFAULT_BRANCH_PREFIX = "ignite-";
+ /**
+ * Service (server) Name.
+ */
+ private String code;
+
+ private String apiUrl;
+
+ private String branchPrefix;
+
+
+ private Properties props;
+
+
+ public GitHubConfig() {
+ }
+
+ public GitHubConfig(String code, Properties props) {
+ this.code = code;
+ this.props = props;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ /**
+ * @param props Properties.
+ */
+ public GitHubConfig properties(Properties props) {
+ this.props = props;
+
+ return this;
+ }
+
+ /**
+ * @param code Name.
+ */
+ public GitHubConfig code(String code) {
+ this.code = code;
+
+ return this;
+ }
+
+ @Override
+ public String gitBranchPrefix() {
+ if (Strings.isNullOrEmpty(branchPrefix)) {
+ if (props != null) {
+ return props.getProperty(HelperConfig.GIT_BRANCH_PREFIX, DEFAULT_BRANCH_PREFIX);
+ } else {
+ return DEFAULT_BRANCH_PREFIX;
+ }
+ }
+ return branchPrefix;
+ }
+}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Fields.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/IGitHubConfig.java
similarity index 70%
copy from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Fields.java
copy to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/IGitHubConfig.java
index 2f6e271..6dbcb4c 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Fields.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/IGitHubConfig.java
@@ -14,22 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-package org.apache.ignite.ci.jira;
-
-import com.google.common.base.MoreObjects;
+package org.apache.ignite.ci.tcbot.conf;
/**
*
*/
-public class Fields {
- /** Ticket status. */
- public Status status;
-
- /** {@inheritDoc} */
- @Override public String toString() {
- return MoreObjects.toStringHelper(this)
- .add("status", status)
- .toString();
- }
-}
\ No newline at end of file
+public interface IGitHubConfig {
+ /** Git branch prefix for search TC runs in PR-less contributions. */
+ public String gitBranchPrefix();
+}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/ITcBotConfig.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/IJiraServerConfig.java
similarity index 53%
copy from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/ITcBotConfig.java
copy to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/IJiraServerConfig.java
index 95948da..7e87a88 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/ITcBotConfig.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/IJiraServerConfig.java
@@ -16,38 +16,36 @@
*/
package org.apache.ignite.ci.tcbot.conf;
-import java.util.Collection;
-import java.util.List;
-import org.apache.ignite.ci.conf.BranchesTracked;
+import com.google.common.base.Strings;
+import org.jetbrains.annotations.Nullable;
/**
- * Teamcity Bot configuration access inteface.
+ * Abstract JIRA server config.
*/
-public interface ITcBotConfig {
- /** Default server id. */
- String DEFAULT_SERVER_ID = "apache";
-
-
- public String primaryServerId();
-
+public interface IJiraServerConfig {
/**
- * @return Tracked branches configuration for TC Bot.
+ * Return JIRA URL, e.g. https://issues.apache.org/jira/
*/
- public BranchesTracked getTrackedBranches();
+ public String getUrl();
/**
- * @return list of internal TC Bot identifiers of all tracked branches.
+ * JIRA project code for filtering out tickets and for adding VISA (JIRA comments).
*/
- public default List<String> getTrackedBranchesIds() {
- return getTrackedBranches().getIds();
- }
+ public String projectCodeForVisa();
/**
- * @return list of servers (services) identifiers involved into tracked branhes processing.
+ * @return PR name and branch name matching number prefix
*/
- public default Collection<String> getServerIds() {
- return getTrackedBranches().getServerIds();
- }
+ @Nullable
+ public String branchNumPrefix();
+ @Nullable
+ public String decodedHttpAuthToken();
+ /**
+ * @return {@code True} if JIRA authorization token is available.
+ */
+ public default boolean isJiraTokenAvailable() {
+ return !Strings.isNullOrEmpty(decodedHttpAuthToken());
+ }
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/ITcBotConfig.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/ITcBotConfig.java
index 95948da..213835f 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/ITcBotConfig.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/ITcBotConfig.java
@@ -18,17 +18,15 @@ package org.apache.ignite.ci.tcbot.conf;
import java.util.Collection;
import java.util.List;
-import org.apache.ignite.ci.conf.BranchesTracked;
/**
* Teamcity Bot configuration access inteface.
*/
public interface ITcBotConfig {
- /** Default server id. */
- String DEFAULT_SERVER_ID = "apache";
+ /** Default server code. */
+ String DEFAULT_SERVER_CODE = "apache";
-
- public String primaryServerId();
+ public String primaryServerCode();
/**
* @return Tracked branches configuration for TC Bot.
@@ -49,5 +47,9 @@ public interface ITcBotConfig {
return getTrackedBranches().getServerIds();
}
+ public ITcServerConfig getTeamcityConfig(String srvCode);
+
+ public IJiraServerConfig getJiraConfig(String srvCode);
+ public IGitHubConfig getGitConfig(String srvCode);
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Fields.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/ITcServerConfig.java
similarity index 68%
rename from ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Fields.java
rename to ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/ITcServerConfig.java
index 2f6e271..36243fb 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/jira/Fields.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/ITcServerConfig.java
@@ -14,22 +14,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.apache.ignite.ci.tcbot.conf;
-package org.apache.ignite.ci.jira;
-
-import com.google.common.base.MoreObjects;
+import java.util.Properties;
/**
- *
+ * Teamcity Server configuration.
*/
-public class Fields {
- /** Ticket status. */
- public Status status;
+public interface ITcServerConfig {
+ @Deprecated
+ public Properties properties();
+
+ /**
+ * @return Another TC Server (service) config name to use settings from. Filled only for server aliases.
+ */
+ public String reference();
- /** {@inheritDoc} */
- @Override public String toString() {
- return MoreObjects.toStringHelper(this)
- .add("status", status)
- .toString();
- }
-}
\ No newline at end of file
+ public String host();
+}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/JiraServerConfig.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/JiraServerConfig.java
new file mode 100644
index 0000000..66a457a
--- /dev/null
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/JiraServerConfig.java
@@ -0,0 +1,144 @@
+/*
+ * 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.tcbot.conf;
+
+import com.google.common.base.Strings;
+import java.util.ArrayList;
+import java.util.Properties;
+import org.apache.ignite.ci.HelperConfig;
+import org.apache.ignite.ci.conf.PasswordEncoder;
+import org.apache.ignite.ci.jira.pure.Fields;
+import org.jetbrains.annotations.Nullable;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+
+/**
+ *
+ */
+public class JiraServerConfig implements IJiraServerConfig {
+ /** Service (server) Name. */
+ private String code;
+
+ /**
+ * Tickets for commenting in JIRA and finding out PA tickets. Default project is "IGNITE".
+ */
+ private String projectCode;
+
+ /**
+ * Branch number prefix. Optional, if not present {@link #projectCode}-NNNNN is searched.
+ * But if branch has different enumeration, this prefix will be searched instead.
+ * If specified, that meant tickets maching branches have another identification.
+ * For exaple some ticket having ID {@link #projectCode}-N1 will be commented, but a branch will be identified using
+ * {@link #branchNumPrefix}N2 with another number.
+ *
+ * Search of branches will be performed using data in JIRA ticket fields for
+ * {@link #projectCode}-N1, fields are listed in {@link #branchNumPrefixSearchFields}.
+ */
+ private String branchNumPrefix;
+
+ /**
+ * Branch ticket template search fields, list of JIRA fields IDs to be checked for finding out branch.
+ * Available fields are field names from {@link Fields} class.
+ */
+ private ArrayList<String> branchNumPrefixSearchFields;
+
+ private Properties props;
+
+ /**
+ * JIRA Auth token to access, use {@link org.apache.ignite.ci.conf.PasswordEncoder#encodeJiraTok(String, String)}
+ */
+ private String authTok;
+
+ /**
+ * JIRA Server URL. HTTPs is highly recommended.
+ */
+ private String url;
+
+ public JiraServerConfig() {
+ }
+
+ public JiraServerConfig(String code, Properties props) {
+ this.code = code;
+ this.props = props;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ /**
+ * @param props Properties.
+ */
+ public JiraServerConfig properties(Properties props) {
+ this.props = props;
+
+ return this;
+ }
+
+ /**
+ * @param code Name.
+ */
+ public JiraServerConfig code(String code) {
+ this.code = code;
+
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getUrl() {
+ if (Strings.isNullOrEmpty(url) && props != null)
+ return props.getProperty(HelperConfig.JIRA_URL);
+
+ return url;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String projectCodeForVisa() {
+ if(Strings.isNullOrEmpty(projectCode) && props!=null) {
+ String ticketPref = props.getProperty(HelperConfig.JIRA_TICKET_TEMPLATE, "IGNITE-");
+
+ return ticketPref.replaceAll("-", "");
+ }
+
+ return projectCode;
+ }
+
+ /** {@inheritDoc} */
+ @Nullable @Override public String branchNumPrefix() {
+ return Strings.emptyToNull(branchNumPrefix);
+ }
+
+ /**
+ * Extracts JIRA basic authorization token from properties.
+ *
+ * @return Null or decoded auth token for Github.
+ */
+ @Nullable
+ @Override
+ public String decodedHttpAuthToken() {
+ String tok;
+ if (Strings.isNullOrEmpty(authTok) && props != null)
+ tok = props.getProperty(HelperConfig.JIRA_AUTH_TOKEN);
+ else
+ tok = authTok;
+
+ if (isNullOrEmpty(tok))
+ return null;
+
+ return PasswordEncoder.decode(tok);
+ }
+}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/LocalFilesBasedConfig.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/LocalFilesBasedConfig.java
index f510061..440f121 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/LocalFilesBasedConfig.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/LocalFilesBasedConfig.java
@@ -16,8 +16,10 @@
*/
package org.apache.ignite.ci.tcbot.conf;
+import com.google.common.base.Strings;
+import java.io.File;
+import java.util.Properties;
import org.apache.ignite.ci.HelperConfig;
-import org.apache.ignite.ci.conf.BranchesTracked;
import org.apache.ignite.ci.di.cache.GuavaCached;
/**
@@ -25,12 +27,56 @@ import org.apache.ignite.ci.di.cache.GuavaCached;
*/
public class LocalFilesBasedConfig implements ITcBotConfig {
/** {@inheritDoc} */
- @GuavaCached(softValues = true, expireAfterAccessSecs = 3 * 60)
+ @GuavaCached(softValues = true, expireAfterWriteSecs = 3 * 60)
@Override public BranchesTracked getTrackedBranches() {
return HelperConfig.getTrackedBranches();
}
- @Override public String primaryServerId() {
- return ITcBotConfig.DEFAULT_SERVER_ID;
+ /** {@inheritDoc} */
+ @Override public ITcServerConfig getTeamcityConfig(String srvCode) {
+ return getTrackedBranches().getTcConfig(srvCode)
+ .orElseGet(() -> {
+ TcServerConfig tcCfg = new TcServerConfig();
+
+ tcCfg.code(srvCode);
+
+ Properties props = loadOldAuthProps(srvCode);
+
+ tcCfg.properties(props);
+
+ return tcCfg;
+ });
}
+
+ @Override public IJiraServerConfig getJiraConfig(String srvCode) {
+ return getTrackedBranches().getJiraConfig(srvCode)
+ .orElseGet(() -> new JiraServerConfig()
+ .code(srvCode)
+ .properties(loadOldAuthProps(srvCode)));
+ }
+
+ @Override
+ public IGitHubConfig getGitConfig(String srvCode) {
+ return getTrackedBranches().getGitHubConfig(srvCode)
+ .orElseGet(() -> new GitHubConfig()
+ .code(srvCode)
+ .properties(loadOldAuthProps(srvCode)));
+ }
+
+ /** {@inheritDoc} */
+ @Override public String primaryServerCode() {
+ String srvCode = getTrackedBranches().primaryServerCode();
+
+ return Strings.isNullOrEmpty(srvCode) ? ITcBotConfig.DEFAULT_SERVER_CODE : srvCode;
+ }
+
+
+ private Properties loadOldAuthProps(String srvCode) {
+ File workDir = HelperConfig.resolveWorkDir();
+
+ String cfgName = HelperConfig.prepareConfigName(srvCode);
+
+ return HelperConfig.loadAuthProperties(workDir, cfgName);
+ }
+
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/TcServerConfig.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/TcServerConfig.java
new file mode 100644
index 0000000..49756ec
--- /dev/null
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/conf/TcServerConfig.java
@@ -0,0 +1,102 @@
+/*
+ * 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.tcbot.conf;
+
+import com.google.common.base.Strings;
+import java.util.Properties;
+import javax.annotation.Nonnull;
+import org.apache.ignite.ci.HelperConfig;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Teamcity connection configuration or reference to another config.
+ */
+public class TcServerConfig implements ITcServerConfig {
+ private static final String DEFAULT_HOST = "https://ci.ignite.apache.org/";
+
+ /** TC server name. */
+ @Nonnull private String code;
+
+ /** Name of server this config points to. This config is just an alias for TC Server. */
+ @Nullable
+ private String reference;
+
+ @Nullable private Properties props;
+
+ /** Host. */
+ @Nullable private String host;
+
+ public TcServerConfig() {
+
+ }
+
+ public TcServerConfig(String code, Properties properties) {
+ this.code = code;
+ this.props = properties;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Properties properties() {
+ if (props == null)
+ return new Properties();
+
+ return props;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String reference() {
+ return reference;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String host() {
+ final String hostConf = hostConfigured().trim();
+
+ return hostConf + (hostConf.endsWith("/") ? "" : "/");
+ }
+
+ /**
+ * Configured value for host.
+ */
+ @NotNull
+ private String hostConfigured() {
+ if (Strings.isNullOrEmpty(host)) {
+ if (props != null)
+ return props.getProperty(HelperConfig.HOST, DEFAULT_HOST);
+ } else {
+ return DEFAULT_HOST;
+ }
+
+ return host;
+ }
+
+ /**
+ * @param props Properties.
+ */
+ public void properties(Properties props) {
+ this.props = props;
+ }
+
+ public void code(String srvCode) {
+ this.code = srvCode;
+ }
+}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/BranchTicketMatcher.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/BranchTicketMatcher.java
new file mode 100644
index 0000000..6cd746e
--- /dev/null
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/visa/BranchTicketMatcher.java
@@ -0,0 +1,302 @@
+/*
+ * 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.tcbot.visa;
+
+import com.google.common.base.Strings;
+import org.apache.ignite.ci.di.cache.GuavaCached;
+import org.apache.ignite.ci.github.PullRequest;
+import org.apache.ignite.ci.github.ignited.IGitHubConnIgnitedProvider;
+import org.apache.ignite.ci.github.pure.IGitHubConnection;
+import org.apache.ignite.ci.jira.ignited.IJiraIgnitedProvider;
+import org.apache.ignite.ci.jira.ignited.TicketCompacted;
+import org.apache.ignite.ci.jira.pure.Ticket;
+import org.apache.ignite.ci.tcbot.conf.IGitHubConfig;
+import org.apache.ignite.ci.tcbot.conf.IJiraServerConfig;
+import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.inject.Inject;
+import javax.ws.rs.QueryParam;
+import java.util.Collection;
+import java.util.Objects;
+
+public class BranchTicketMatcher {
+ /** Config. */
+ @Inject private ITcBotConfig cfg;
+
+ /** GitHub connection ignited provider. */
+ @Inject private IGitHubConnIgnitedProvider gitHubProvider;
+
+ /** JIRA provider */
+ @Inject private IJiraIgnitedProvider jiraIgnProv;
+
+ @Nullable
+ public String resolveTcBranchForPrLess(Ticket ticket,
+ IJiraServerConfig jiraCfg,
+ IGitHubConfig gitHubConfig) {
+ String branchNumPrefix = jiraCfg.branchNumPrefix();
+
+ if (Strings.isNullOrEmpty(branchNumPrefix)) {
+ //an easy way, no special branch and ticket mappings specified, use project code.
+ int ticketId = ticket.keyWithoutProject(jiraCfg.projectCodeForVisa());
+
+ return gitHubConfig.gitBranchPrefix() + ticketId;
+ }
+
+ String branchJiraIdentification = findFixPrefixedNoInValues(branchNumPrefix,
+ ticket.key,
+ ticket.fields.summary,
+ ticket.fields.customfield_11050);
+
+ return convertJiraToGit(branchJiraIdentification, branchNumPrefix, gitHubConfig);
+
+ }
+
+ /**
+ * Converts JIRA notation branch name to actual git branch name. Usually it is just lower-casing, but any mapping may be configured.
+ * @param branchJiraIdentification Branch jira identification.
+ * @param branchNumPrefix Branch number prefix.
+ * @param gitHubConfig GH connection config.
+ */
+ private String convertJiraToGit(String branchJiraIdentification,
+ String branchNumPrefix,
+ IGitHubConfig gitHubConfig) {
+ if (Strings.isNullOrEmpty(branchJiraIdentification))
+ return null;
+
+ return gitHubConfig.gitBranchPrefix() + branchJiraIdentification.substring(branchNumPrefix.length());
+ }
+
+ /**
+ * @param tickets Tickets.
+ * @param pr Pr.
+ * @param jiraCfg Jira config.
+ */
+ @Nullable public String resolveTicketIdForPrBasedContrib(Collection<Ticket> tickets, PullRequest pr, IJiraServerConfig jiraCfg) {
+ String branchNumPrefix = jiraCfg.branchNumPrefix();
+
+ if (Strings.isNullOrEmpty(branchNumPrefix)) {
+ //an easy way, no special branch and ticket mappings specified, use project code.
+ String jiraPrefix = jiraCfg.projectCodeForVisa() + TicketCompacted.PROJECT_DELIM;
+
+ return findFixPrefixedNumber(pr.getTitle(), jiraPrefix);
+ }
+
+ String prTitle = pr.getTitle();
+
+ String branchNum = findFixPrefixedNumber(prTitle, branchNumPrefix);
+
+ if (branchNum == null) // PR does not mention
+ return null;
+
+ return findTicketMentions(tickets, branchNum);
+ }
+
+ @SuppressWarnings("WeakerAccess")
+ @GuavaCached(maximumSize = 3000, expireAfterWriteSecs = 60, cacheNullRval = true)
+ protected String findTicketMentions(String srvCode, @Nullable String branchNum) {
+ return findTicketMentions(jiraIgnProv.server(srvCode).getTickets(), branchNum);
+ }
+
+ @Nullable private String findTicketMentions(Collection<Ticket> tickets, @Nullable String branchNum) {
+ if (Strings.isNullOrEmpty(branchNum))
+ return null;
+
+ return tickets.stream()
+ .map(t -> t.key)
+ .filter(k -> Objects.equals(k, branchNum))
+ .findFirst()
+ .orElseGet(() -> findTicketMentionsInSupplementaryFields(tickets, branchNum));
+ }
+
+ @Nullable private String findTicketMentionsInSupplementaryFields(Collection<Ticket> tickets, String branchNum) {
+ if (Strings.isNullOrEmpty(branchNum))
+ return null;
+
+ return tickets.stream()
+ .filter(t -> mentionsBranch(branchNum, t))
+ .findFirst()
+ .map(t -> t.key)
+ .orElse(null);
+ }
+
+ /**
+ * @param branchName Full branch name in jira.
+ * @param ticket Ticket.
+ */
+ private boolean mentionsBranch(String branchName, Ticket ticket) {
+ String summary = ticket.fields.summary;
+ if (summary != null && summary.contains(branchName))
+ return true;
+
+ String val = ticket.fields.customfield_11050;
+ if (val != null && val.contains(branchName))
+ return true;
+
+ return false;
+ }
+
+
+ @Nullable
+ private String findFixPrefixedNoInValues(@NotNull String prefix, String... values) {
+ for (String value : values) {
+ String fixPrefixedNumber = findFixPrefixedNumber(value, prefix);
+
+ if (fixPrefixedNumber != null)
+ return fixPrefixedNumber;
+ }
+ return null;
+ }
+ /**
+ * @param value Pull Request/Ticket title prefix or other text to find constant-prefix text.
+ * @param prefix Ticket prefix.
+ * @return Branch number or null.
+ */
+ @Nullable
+ private String findFixPrefixedNumber(@Nullable String value, @NotNull String prefix) {
+ if(Strings.isNullOrEmpty(value))
+ return null;
+
+ int idxOfBranchNum = value.toUpperCase().indexOf(prefix.toUpperCase());
+
+ if (idxOfBranchNum < 0)
+ return null;
+
+ int beginIdx = prefix.length() + idxOfBranchNum;
+ int endIdx = beginIdx;
+
+ while (endIdx < value.length() && Character.isDigit(value.charAt(endIdx)))
+ endIdx++;
+
+ if (endIdx == beginIdx)
+ return null;
+
+ return prefix + value.substring(beginIdx, endIdx);
+ }
+
+ public static class TicketNotFoundException extends Exception {
+ TicketNotFoundException(String msg) {
+ super(msg);
+ }
+
+ TicketNotFoundException(String msg, Exception e) {
+ super(msg, e);
+ }
+ }
+
+
+ public String resolveTicketFromBranch(String srvCode, String ticketFullName, String branchForTc) throws TicketNotFoundException {
+ if(!Strings.isNullOrEmpty(ticketFullName))
+ return ticketFullName; //old code probably not needed now; ticketFullName = ticketFullName.toUpperCase().startsWith(prefix) ? ticketFullName : prefix + ticketFullName;
+
+ IJiraServerConfig jiraCfg = cfg.getJiraConfig(srvCode);
+ IGitHubConfig gitConfig = cfg.getGitConfig(srvCode);
+
+ PullRequest pr; // filled only when special PR found
+
+ String ticketPrefix;
+ try {
+ String branchNumPrefix = jiraCfg.branchNumPrefix();
+
+ ticketPrefix = Strings.isNullOrEmpty(branchNumPrefix)
+ ? jiraCfg.projectCodeForVisa() + TicketCompacted.PROJECT_DELIM
+ : branchNumPrefix;
+
+ String prLessTicket = prLessTicket(branchForTc, ticketPrefix, gitConfig);
+ if (!Strings.isNullOrEmpty(prLessTicket)) {
+ if (Strings.isNullOrEmpty(branchNumPrefix)) {
+ //Default, simple case
+
+ return prLessTicket; //find out PRless ticket,
+ } else {
+ // PR less ticket only mentioned in real ticket
+ String ticket = findTicketMentions(srvCode, prLessTicket);
+
+ if (!Strings.isNullOrEmpty(ticket))
+ return ticket; // found real JIRA ticket for comment
+ }
+ }
+
+ pr = findPrForBranch(srvCode, branchForTc);
+ if (pr != null) {
+ String jiraPrefixInPr = findFixPrefixedNumber(pr.getTitle(), ticketPrefix);
+
+ String ticketFromPr;
+ if (Strings.isNullOrEmpty(branchNumPrefix)) {
+ //Default, simple case, branch name matching gives us a ticket
+ ticketFromPr = jiraPrefixInPr;
+ } else {
+ ticketFromPr = Strings.isNullOrEmpty(jiraPrefixInPr)
+ ? null
+ : findTicketMentions(srvCode, jiraPrefixInPr);
+ }
+
+ if (!Strings.isNullOrEmpty(ticketFromPr))
+ return ticketFromPr; // found real JIRA ticket for comment
+ }
+ } catch (Exception e) {
+ throw new TicketNotFoundException("Exception happened when server tried to get ticket ID from Pull Request - " + e.getMessage(), e);
+ }
+
+ throw new TicketNotFoundException("JIRA ticket can't be found - " +
+ "PR title \"" + (pr == null ? "" : pr.getTitle()) + "\" should starts with \"" + ticketPrefix + "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>" +
+ " or use branch name according ticket name.");
+ }
+
+ @Nullable
+ private PullRequest findPrForBranch(
+ @Nullable @QueryParam("serverId") String srvId,
+ @Nullable @QueryParam("branchName") String branchForTc) {
+ Integer prId = IGitHubConnection.convertBranchToPrId(branchForTc);
+
+ if (prId == null)
+ return null;
+
+ return gitHubProvider.server(srvId).getPullRequest(prId);
+ }
+
+
+
+ /**
+ * @param branchForTc Branch for tc.
+ * @param ticketPrefix JIRA Ticket prefix.
+ * @param gitHubIgn GitHub connection ign.
+ */
+ @Nullable
+ private static String prLessTicket(String branchForTc,
+ String ticketPrefix,
+ IGitHubConfig gitHubIgn) {
+ String branchPrefix = gitHubIgn.gitBranchPrefix();
+
+ if (!branchForTc.startsWith(branchPrefix))
+ return null;
+
+ try {
+ int ticketNum = Integer.parseInt(branchForTc.substring(branchPrefix.length()));
+
+ return ticketPrefix + ticketNum;
+ }
+ catch (NumberFormatException ignored) {
+ }
+ return null;
+ }
+}
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 05031c7..44e3bb1 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
@@ -35,22 +35,21 @@ import java.util.stream.Stream;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.ws.rs.QueryParam;
-import org.apache.ignite.ci.HelperConfig;
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.jira.Ticket;
+import org.apache.ignite.ci.jira.pure.Ticket;
import org.apache.ignite.ci.jira.ignited.IJiraIgnited;
import org.apache.ignite.ci.jira.ignited.IJiraIgnitedProvider;
-import org.apache.ignite.ci.jira.pure.IJiraIntegrationProvider;
import org.apache.ignite.ci.observer.BuildObserver;
import org.apache.ignite.ci.observer.BuildsInfo;
import org.apache.ignite.ci.tcbot.ITcBotBgAuth;
import org.apache.ignite.ci.tcbot.chain.PrChainsProcessor;
+import org.apache.ignite.ci.tcbot.conf.IJiraServerConfig;
+import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
import org.apache.ignite.ci.tcmodel.mute.MuteInfo;
import org.apache.ignite.ci.tcmodel.result.Build;
import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
@@ -109,11 +108,8 @@ public class TcBotTriggerAndSignOffService {
/** TC ignited provider. */
@Inject ITeamcityIgnitedProvider tcIgnitedProv;
- /** Direct connection to JIRA provider */
- @Inject IJiraIgnitedProvider jiraIgnProv;
-
- /** Direct connection to JIRA provider */
- @Inject IJiraIntegrationProvider jiraPureProvider;
+ /** JIRA provider */
+ @Inject private IJiraIgnitedProvider jiraIgnProv;
/** */
@Inject private VisasHistoryStorage visasHistStorage;
@@ -129,6 +125,11 @@ public class TcBotTriggerAndSignOffService {
@Inject PrChainsProcessor prChainsProcessor;
+ /** Config. */
+ @Inject ITcBotConfig cfg;
+
+ @Inject BranchTicketMatcher ticketMatcher;
+
/** Jackson serializer. */
private final ObjectMapper objMapper = new ObjectMapper();
@@ -241,25 +242,7 @@ public class TcBotTriggerAndSignOffService {
}
}
- /**
- * @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 = prefix + pr.getTitle().substring(beginIdx, endIdx);
- }
-
- return ticketId;
- }
@NotNull public String triggerBuildsAndObserve(
@Nullable String srvId,
@@ -303,40 +286,13 @@ public class TcBotTriggerAndSignOffService {
String parentSuiteId,
Build... builds
) {
- IJiraIgnited jiraIntegration = jiraIgnProv.server(srvId);
-
- String prefix = jiraIntegration.ticketPrefix();
-
- if (F.isEmpty(ticketFullName)) {
- try {
- ticketFullName = prLessTicket(srvId, branchForTc, prov, prefix);
-
- PullRequest pr = null;
-
- if (Strings.isNullOrEmpty(ticketFullName)) {
- pr = findPrForBranch(srvId, branchForTc);
-
- if (pr != null)
- ticketFullName = getTicketFullName(pr, prefix);
- }
-
- if (Strings.isNullOrEmpty(ticketFullName)) {
- return "JIRA ticket will not be notified - " +
- "PR title \"" + (pr == null ? "" : 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>" +
- " or use branch name according ticket name.";
- }
- }
- catch (Exception e) {
- return "JIRA ticket will not be notified after the tests are completed - " +
- "exception happened when server tried to get ticket ID from Pull Request [errMsg=" +
- e.getMessage() + ']';
- }
- } else {
- //todo remove once every ticket is with Ignite prefix
- ticketFullName = ticketFullName.toUpperCase().startsWith(prefix) ? ticketFullName : prefix + ticketFullName;
+ try {
+ ticketFullName = ticketMatcher.resolveTicketFromBranch(srvId, ticketFullName, branchForTc);
+ } catch (BranchTicketMatcher.TicketNotFoundException e) {
+ logger.info("", e);
+ return "JIRA ticket will not be notified after the tests are completed - " +
+ "exception happened when server tried to get ticket ID from Pull Request [errMsg="
+ + e.getMessage();
}
buildObserverProvider.get().observe(srvId, prov, ticketFullName, branchForTc, parentSuiteId, builds);
@@ -361,103 +317,28 @@ public class TcBotTriggerAndSignOffService {
@QueryParam("suiteId") @Nullable String suiteId,
@QueryParam("ticketId") @Nullable String ticketFullName,
ICredentialsProv prov) {
- String jiraRes = "";
-
- String prefix = jiraIgnProv.server(srvId).ticketPrefix();
- if (Strings.isNullOrEmpty(ticketFullName)) {
- try {
- ticketFullName = prLessTicket(srvId, branchForTc, prov, prefix);
-
- PullRequest pr = null;
-
- if (Strings.isNullOrEmpty(ticketFullName)) {
- pr = findPrForBranch(srvId, branchForTc);
-
- if (pr != null)
- ticketFullName = getTicketFullName(pr, prefix);
- }
-
- if (Strings.isNullOrEmpty(ticketFullName)) {
- jiraRes = "JIRA ticket can't be commented - " +
- "PR title \"" + (pr == null ? "" : 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>" +
- " or use branch name according ticket name.";
- }
- }
- catch (RuntimeException e) {
- jiraRes = "Exception happened when server tried to get ticket ID from Pull Request - " + e.getMessage();
- }
- } else {
- //todo remove once every ticket is with IGnite prefix
- ticketFullName = ticketFullName.toUpperCase().startsWith(prefix) ? ticketFullName : prefix + ticketFullName;
+ try {
+ ticketFullName = ticketMatcher.resolveTicketFromBranch(srvId, ticketFullName, branchForTc);
+ } catch (BranchTicketMatcher.TicketNotFoundException e) {
+ logger.info("", e);
+ return new SimpleResult("JIRA wasn't commented.<br>" + e.getMessage());
}
- if (!Strings.isNullOrEmpty(ticketFullName)) {
- BuildsInfo buildsInfo = new BuildsInfo(srvId, prov, ticketFullName, branchForTc, suiteId);
+ BuildsInfo buildsInfo = new BuildsInfo(srvId, prov, ticketFullName, branchForTc, suiteId);
- VisaRequest lastVisaReq = visasHistStorage.getLastVisaRequest(buildsInfo.getContributionKey());
+ VisaRequest lastVisaReq = visasHistStorage.getLastVisaRequest(buildsInfo.getContributionKey());
- if (Objects.nonNull(lastVisaReq) && lastVisaReq.isObserving())
- return new SimpleResult("Jira wasn't commented." +
+ if (Objects.nonNull(lastVisaReq) && lastVisaReq.isObserving())
+ return new SimpleResult("Jira wasn't commented." +
" \"Re-run possible blockers & Comment JIRA\" was triggered for current branch." +
" Wait for the end or cancel exsiting observing.");
- Visa visa = notifyJira(srvId, prov, suiteId, branchForTc, ticketFullName);
+ Visa visa = notifyJira(srvId, prov, suiteId, branchForTc, ticketFullName);
- visasHistStorage.put(new VisaRequest(buildsInfo).setResult(visa));
+ visasHistStorage.put(new VisaRequest(buildsInfo).setResult(visa));
- return new SimpleResult(visa.status);
- }
- else
- return new SimpleResult("JIRA wasn't commented." + (!jiraRes.isEmpty() ? "<br>" + jiraRes : ""));
- }
-
- @Nullable public PullRequest findPrForBranch(
- @Nullable @QueryParam("serverId") String srvId,
- @Nullable @QueryParam("branchName") String branchForTc) {
- Integer prId = IGitHubConnection.convertBranchToId(branchForTc);
-
- if (prId == null)
- return null;
-
- IGitHubConnIgnited gh = gitHubConnIgnitedProvider.server(srvId);
-
- return gh.getPullRequest(prId);
- }
-
- /**
- * @param srvId Server id.
- * @param branchForTc Branch for tc.
- * @param prov Credentials Prov.
- * @param ticketPrefix Ticket prefix.
- */
- @Nullable public String prLessTicket(@Nullable @QueryParam("serverId") String srvId,
- String branchForTc, ICredentialsProv prov, String ticketPrefix) {
- return prLessTicket(branchForTc, ticketPrefix, tcIgnitedProv.server(srvId, prov));
- }
-
- /**
- * @param branchForTc Branch for tc.
- * @param ticketPrefix Ticket prefix.
- * @param tcIgn Tc ign.
- */
- @Nullable public static String prLessTicket(String branchForTc, String ticketPrefix, ITeamcityIgnited tcIgn) {
- String branchPrefix = tcIgn.gitBranchPrefix();
-
- if (!branchForTc.startsWith(branchPrefix))
- return null;
-
- try {
- int ticketNum = Integer.parseInt(branchForTc.substring(branchPrefix.length()));
-
- return ticketPrefix + ticketNum;
- }
- catch (NumberFormatException ignored) {
- }
- return null;
+ return new SimpleResult(visa.status);
}
/**
@@ -468,10 +349,14 @@ public class TcBotTriggerAndSignOffService {
ICredentialsProv credsProv) {
IJiraIgnited jiraIntegration = jiraIgnProv.server(srvId);
- List<PullRequest> requests = gitHubConnIgnitedProvider.server(srvId).getPullRequests();
+ IGitHubConnIgnited gitHubConnIgnited = gitHubConnIgnitedProvider.server(srvId);
+ List<PullRequest> requests = gitHubConnIgnited.getPullRequests();
if (requests == null)
return null;
+ Set<Ticket> tickets = jiraIntegration.getTickets();
+
+ List<Ticket> paTickets = tickets.stream().filter(Ticket::isActiveContribution).collect(Collectors.toList());
List<ContributionToCheck> contribsList = requests.stream().map(pr -> {
ContributionToCheck check = new ContributionToCheck();
@@ -490,8 +375,9 @@ public class TcBotTriggerAndSignOffService {
check.prAuthorAvatarUrl = "";
}
- String prefix = jiraIntegration.ticketPrefix();
- check.jiraIssueId = Strings.emptyToNull(getTicketFullName(pr, prefix));
+ IJiraServerConfig jiraCfg = jiraIntegration.config();
+
+ check.jiraIssueId = ticketMatcher.resolveTicketIdForPrBasedContrib(tickets, pr, jiraCfg);
if (!Strings.isNullOrEmpty(check.jiraIssueId))
check.jiraIssueUrl = jiraIntegration.generateTicketUrl(check.jiraIssueId);
@@ -499,20 +385,19 @@ public class TcBotTriggerAndSignOffService {
return check;
}).collect(Collectors.toList());
-
- Set<Ticket> tickets = jiraIntegration.getTickets();
-
- List<Ticket> paTickets = tickets.stream().filter(Ticket::isActiveContribution).collect(Collectors.toList());
-
ITeamcityIgnited tcIgn = tcIgnitedProv.server(srvId, credsProv);
paTickets.forEach(ticket -> {
- int ticketId = ticket.igniteId(jiraIntegration.ticketPrefix());
- String branch = tcIgn.gitBranchPrefix() + ticketId;
+ String branch = ticketMatcher.resolveTcBranchForPrLess(ticket,
+ jiraIntegration.config(),
+ gitHubConnIgnited.config());
- String defBtForMaster = findDefaultBranchBuildType(srvId);
+ if (branch == null)
+ return; // nothing to do if branch was not resolved
- if(tcIgn.getAllBuildsCompacted(defBtForMaster, branch).isEmpty())
+ String defBtForMaster = findDefaultBranchBuildType(tcIgn.serverId());
+
+ if (tcIgn.getAllBuildsCompacted(defBtForMaster, branch).isEmpty())
return; //Skipping contributions without builds
ContributionToCheck contribution = new ContributionToCheck();
@@ -521,8 +406,8 @@ public class TcBotTriggerAndSignOffService {
contribution.jiraIssueUrl = jiraIntegration.generateTicketUrl( ticket.key);
contribution.tcBranchName = branch;
- contribution.prNumber = -ticketId;
- contribution.prTitle = ""; //todo ticket title
+ contribution.prNumber = -ticket.keyWithoutProject(jiraIntegration.config().projectCodeForVisa());
+ contribution.prTitle = ticket.fields.summary;
contribution.prHtmlUrl = "";
contribution.prTimeUpdate = ""; //todo ticket updateTime
@@ -538,7 +423,7 @@ public class TcBotTriggerAndSignOffService {
@Nonnull private List<BuildRefCompacted> findBuildsForPr(String suiteId, String prId,
IGitHubConnIgnited ghConn, ITeamcityIgnited srv) {
- List<BuildRefCompacted> buildHist = srv.getAllBuildsCompacted(suiteId, branchForTcDefault(prId, srv));
+ List<BuildRefCompacted> buildHist = srv.getAllBuildsCompacted(suiteId, branchForTcDefault(prId, ghConn));
if (!buildHist.isEmpty())
return buildHist;
@@ -570,7 +455,7 @@ public class TcBotTriggerAndSignOffService {
return Collections.emptyList();
}
- private String branchForTcDefault(String prId, ITeamcityIgnited srv) {
+ private String branchForTcDefault(String prId, IGitHubConnIgnited srv) {
Integer prNum = Integer.valueOf(prId);
if (prNum < 0)
return srv.gitBranchPrefix() + (-prNum); // Checking "ignite-10930" builds only
@@ -599,7 +484,7 @@ public class TcBotTriggerAndSignOffService {
IGitHubConnIgnited ghConn = gitHubConnIgnitedProvider.server(srvId);
- String defBtForMaster = findDefaultBranchBuildType(srvId);
+ String defBtForMaster = findDefaultBranchBuildType(teamcity.serverId());
BuildTypeCompacted buildType = Strings.isNullOrEmpty(defBtForMaster)
? null
@@ -629,8 +514,8 @@ public class TcBotTriggerAndSignOffService {
List<BuildRefCompacted> compBuilds = findBuildsForPr(btId, prId, ghConn, teamcity);
statuses.add(compBuilds.isEmpty()
- ? new ContributionCheckStatus(btId, branchForTcDefault(prId, teamcity))
- : contributionStatus(srvId, btId, compBuilds, teamcity, prId));
+ ? new ContributionCheckStatus(btId, branchForTcDefault(prId, ghConn))
+ : contributionStatus(srvId, btId, compBuilds, teamcity, ghConn, prId));
}
return statuses;
@@ -639,7 +524,8 @@ public class TcBotTriggerAndSignOffService {
@NotNull public String findDefaultBranchBuildType(String srvId) {
StringBuilder buildTypeId = new StringBuilder();
- HelperConfig.getTrackedBranches().get(DEFAULT_TRACKED_BRANCH_NAME)
+ cfg.getTrackedBranches()
+ .get(DEFAULT_TRACKED_BRANCH_NAME)
.ifPresent(
b -> b.getChainsStream()
.filter(c -> Objects.equals(srvId, c.serverId))
@@ -654,9 +540,10 @@ public class TcBotTriggerAndSignOffService {
* @param srvId Server id.
* @param suiteId Suite id.
* @param builds Build references.
+ * @param ghConn
*/
public ContributionCheckStatus contributionStatus(String srvId, String suiteId, List<BuildRefCompacted> builds,
- ITeamcityIgnited teamcity, String prId) {
+ ITeamcityIgnited teamcity, IGitHubConnIgnited ghConn, String prId) {
ContributionCheckStatus status = new ContributionCheckStatus();
status.suiteId = suiteId;
@@ -679,7 +566,7 @@ public class TcBotTriggerAndSignOffService {
status.resolvedBranch = status.branchWithFinishedSuite;
//todo take into account running/queued
else
- status.resolvedBranch = !builds.isEmpty() ? builds.get(0).branchName(compactor) : branchForTcDefault(prId, teamcity);
+ status.resolvedBranch = !builds.isEmpty() ? builds.get(0).branchName(compactor) : branchForTcDefault(prId, ghConn);
String observationsStatus = buildObserverProvider.get().getObservationStatus(new ContributionKey(srvId, status.resolvedBranch));
@@ -878,5 +765,4 @@ public class TcBotTriggerAndSignOffService {
return xmlEscapeText(res.toString());
}
-
}
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 df2099a..e1eca89 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
@@ -189,9 +189,6 @@ public interface ITeamcityIgnited {
public List<String> getAllProjectsIds();
- public String gitBranchPrefix();
-
-
/**
* Get list of teamcity agents. Never cached, request goes directly to pure TC.
*
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnitedProvider.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnitedProvider.java
index 4c0fb56..0497527 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnitedProvider.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/ITeamcityIgnitedProvider.java
@@ -18,14 +18,22 @@ package org.apache.ignite.ci.teamcity.ignited;
import javax.annotation.Nullable;
import org.apache.ignite.ci.user.ICredentialsProv;
+import org.apache.ignite.ci.web.rest.exception.ServiceUnauthorizedException;
/**
* Provides instance of particular cache-based teamcity connection.
*/
public interface ITeamcityIgnitedProvider {
+ public boolean hasAccess(String srvId, @Nullable ICredentialsProv prov);
+
/**
* @param srvId Server id.
* @param prov Prov.
*/
public ITeamcityIgnited server(String srvId, @Nullable ICredentialsProv prov);
+
+ default void checkAccess(@Nullable String srvId, ICredentialsProv credsProv) {
+ if (!hasAccess(srvId, credsProv))
+ throw ServiceUnauthorizedException.noCreds(srvId);
+ }
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TcIgnitedCachingProvider.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TcIgnitedCachingProvider.java
index ec1afc9..227b99e 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TcIgnitedCachingProvider.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TcIgnitedCachingProvider.java
@@ -25,6 +25,8 @@ import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Provider;
import org.apache.ignite.ci.ITeamcity;
+import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
+import org.apache.ignite.ci.tcbot.conf.ITcServerConfig;
import org.apache.ignite.ci.teamcity.restcached.ITcServerProvider;
import org.apache.ignite.ci.user.ICredentialsProv;
import org.apache.ignite.ci.util.ExceptionUtil;
@@ -37,6 +39,9 @@ class TcIgnitedCachingProvider implements ITeamcityIgnitedProvider {
@Inject
private ITcServerProvider srvFactory;
+ /** Config. */
+ @Inject private ITcBotConfig cfg;
+
@Inject private Provider<TeamcityIgnitedImpl> provider;
private final Cache<String, ITeamcityIgnited> srvs
@@ -47,22 +52,37 @@ class TcIgnitedCachingProvider implements ITeamcityIgnitedProvider {
.build();
/** {@inheritDoc} */
- @Override public ITeamcityIgnited server(String srvId, @Nullable ICredentialsProv prov) {
- String fullKey = Strings.nullToEmpty(prov == null ? null : prov.getUser(srvId)) + ":" + Strings.nullToEmpty(srvId);
+ @Override public boolean hasAccess(String srvId, @Nullable ICredentialsProv prov) {
+ String ref = cfg.getTeamcityConfig(srvId).reference();
+
+ if (!Strings.isNullOrEmpty(ref))
+ return prov.hasAccess(ref);
+
+ return prov.hasAccess(srvId);
+ }
+
+ /** {@inheritDoc} */
+ @Override public ITeamcityIgnited server(String srvIdReq, @Nullable ICredentialsProv prov) {
+ ITcServerConfig cfg = this.cfg.getTeamcityConfig(srvIdReq);
+ String ref = cfg.reference();
+
+ String realSrvId = !Strings.isNullOrEmpty(ref) && !srvIdReq.equals(ref) ? ref : srvIdReq;
+
+ String fullKey = Strings.nullToEmpty(prov == null ? null : prov.getUser(realSrvId)) + ":" + Strings.nullToEmpty(realSrvId);
try {
return srvs.get(fullKey, () -> {
- ITeamcity tcRealConn = srvFactory.server(srvId, prov);
+ ITeamcity tcRealConn = srvFactory.server(realSrvId, prov);
if (prov != null) {
- final String user = prov.getUser(srvId);
- final String pwd = prov.getPassword(srvId);
+ final String user = prov.getUser(realSrvId);
+ final String pwd = prov.getPassword(realSrvId);
tcRealConn.setAuthData(user, pwd);
}
TeamcityIgnitedImpl impl = provider.get();
- impl.init(srvId, tcRealConn);
+ impl.init(realSrvId, tcRealConn);
return impl;
});
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 79aae65..b38350e 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
@@ -419,11 +419,6 @@ public class TeamcityIgnitedImpl implements ITeamcityIgnited {
return conn.getProjects().stream().map(Project::id).collect(Collectors.toList());
}
- /** {@inheritDoc} */
- @Override public String gitBranchPrefix() {
- return conn.gitBranchPrefix();
- }
-
@Override
public List<Agent> agents(boolean connected, boolean authorized) {
return conn.agents(connected, authorized);
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/TestCompacted.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/TestCompacted.java
index b5a8e36..cdd99c7 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/TestCompacted.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/TestCompacted.java
@@ -20,14 +20,11 @@ package org.apache.ignite.ci.teamcity.ignited.fatbuild;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Strings;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.BitSet;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
import org.apache.ignite.ci.analysis.RunStat;
+import org.apache.ignite.ci.tcbot.common.StringFieldCompacted;
import org.apache.ignite.ci.tcmodel.hist.BuildRef;
import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrence;
import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrenceFull;
@@ -201,17 +198,9 @@ public class TestCompacted {
return new String(details, StandardCharsets.UTF_8);
else if (!flag1 && flag2) {
try {
- final ByteArrayInputStream in = new ByteArrayInputStream(details);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- try (final GZIPInputStream gzi = new GZIPInputStream(in)) {
- byte[] outbuf = new byte[details.length];
- int len;
- while ((len = gzi.read(outbuf, 0, outbuf.length)) != -1)
- bos.write(outbuf, 0, len);
- }
-
- return new String(bos.toByteArray(), StandardCharsets.UTF_8);
- } catch (Exception e) {
+ return StringFieldCompacted.unzipToString(details);
+ }
+ catch (Exception e) {
logger.error("GZip.uncompress failed: " + e.getMessage(), e);
return null;
}
@@ -243,18 +232,14 @@ public class TestCompacted {
}
try {
- final ByteArrayOutputStream out = new ByteArrayOutputStream();
- try(final GZIPOutputStream gzipOutputStream = new GZIPOutputStream(out)) {
- gzipOutputStream.write(uncompressed);
- }
- gzip = out.toByteArray();
+ gzip = StringFieldCompacted.zipBytes(uncompressed);
}
catch (Exception e) {
logger.error("Snappy.compress failed: " + e.getMessage(), e);
}
- final int snappyLen = snappy!=null ? snappy.length : -1;
- final int gzipLen = gzip!=null ? gzip.length : -1;
+ final int snappyLen = snappy != null ? snappy.length : -1;
+ final int gzipLen = gzip != null ? gzip.length : -1;
flags.set(COMPRESS_TYPE_FLAG1, true);
flags.set(COMPRESS_TYPE_FLAG2, false);
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 5af968f..d0e38dd 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
@@ -52,8 +52,15 @@ public interface ITeamcityConn {
*/
public String host();
+ /**
+ * @param buildId Build id.
+ */
public Build getBuild(int buildId);
+ /**
+ * @param fullUrl Full url.
+ * @param nextPage Next page.
+ */
public List<BuildRef> getBuildRefsPage(String fullUrl, AtomicReference<String> nextPage);
/**
@@ -82,13 +89,25 @@ public interface ITeamcityConn {
*/
public Build triggerBuild(String buildTypeId, @Nonnull String branchName, boolean cleanRebuild, boolean queueAtTop);
- ProblemOccurrences getProblems(int buildId);
+ /**
+ * @param buildId Build id.
+ */
+ public ProblemOccurrences getProblems(int buildId);
- Statistics getStatistics(int buildId);
+ /**
+ * @param buildId Build id.
+ */
+ public Statistics getStatistics(int buildId);
- ChangesList getChangesList(int buildId);
+ /**
+ * @param buildId Build id.
+ */
+ public ChangesList getChangesList(int buildId);
- Change getChange(int changeId);
+ /**
+ * @param changeId Change id.
+ */
+ public Change getChange(int changeId);
/**
* List of project suites.
@@ -96,23 +115,18 @@ public interface ITeamcityConn {
* @param projectId Project id.
* @return List of buildType's references.
*/
- List<BuildType> getBuildTypes(String projectId);
+ public List<BuildType> getBuildTypes(String projectId);
/**
* @param buildTypeId BuildType id.
* @return BuildType.
*/
- BuildTypeFull getBuildType(String buildTypeId);
+ public BuildTypeFull getBuildType(String buildTypeId);
/**
* @return List of all project available at Teamcity server.
*/
- List<Project> getProjects();
-
- /**
- * @return Branch name mandatory prefix for all PR-less contributions, e.g. "ignite-".
- */
- public String gitBranchPrefix();
+ public List<Project> getProjects();
/**
* Get list of teamcity agents.
@@ -121,5 +135,5 @@ public interface ITeamcityConn {
* @param authorized Authorized flag.
* @return List of teamcity agents.
*/
- List<Agent> agents(boolean connected, boolean authorized);
+ public List<Agent> agents(boolean connected, boolean authorized);
}
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 8c12e42..9ffcf73 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
@@ -33,16 +33,14 @@ import org.apache.ignite.ci.github.PullRequest;
import org.apache.ignite.ci.github.ignited.IGitHubConnIgnited;
import org.apache.ignite.ci.github.pure.IGitHubConnection;
import org.apache.ignite.ci.jira.pure.IJiraIntegration;
-import org.apache.ignite.ci.tcbot.visa.TcBotTriggerAndSignOffService;
+import org.apache.ignite.ci.tcbot.visa.BranchTicketMatcher;
import org.apache.ignite.ci.tcmodel.conf.BuildType;
import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
import org.apache.ignite.ci.util.CollectionUtil;
import org.apache.ignite.internal.util.typedef.T2;
import static org.apache.ignite.ci.util.UrlUtil.escape;
-import static org.apache.ignite.ci.web.model.current.SuiteCurrentStatus.branchForLink;
-import static org.apache.ignite.ci.web.model.current.SuiteCurrentStatus.createOccurForLogConsumer;
-import static org.apache.ignite.ci.web.model.current.SuiteCurrentStatus.createOrrucForLongRun;
+import static org.apache.ignite.ci.web.model.current.SuiteCurrentStatus.*;
/**
* Represent Run All chain results/ or RunAll+latest re-runs.
@@ -51,7 +49,7 @@ import static org.apache.ignite.ci.web.model.current.SuiteCurrentStatus.createOr
*/
@SuppressWarnings({"WeakerAccess", "PublicField"})
public class ChainAtServerCurrentStatus {
- /** {@link BuildType#name} */
+ /** {@link BuildType#getName()} */
public String chainName;
/** Server ID. */
@@ -123,29 +121,31 @@ public class ChainAtServerCurrentStatus {
}
/** */
- public void initJiraAndGitInfo(ITeamcityIgnited tcIgnited,
- IJiraIntegration jiraIntegration, IGitHubConnIgnited gitHubConnIgnited) {
- Integer prNum = IGitHubConnection.convertBranchToId(branchName);
-
- String prUrl = null;
+ public void initJiraAndGitInfo(BranchTicketMatcher ticketMatcher,
+ IJiraIntegration jiraIntegration,
+ IGitHubConnIgnited gitHubConnIgnited) {
String ticketFullName = null;
+ try {
+ ticketFullName = ticketMatcher
+ .resolveTicketFromBranch(jiraIntegration.getServiceId(),
+ null,
+ branchName);
+ } catch (BranchTicketMatcher.TicketNotFoundException ignore) {
+ }
- String ticketUrl = null;
+ Integer prNum = IGitHubConnection.convertBranchToPrId(branchName);
- String ticketPrefix = jiraIntegration.ticketPrefix();
+ String prUrl = null;
+ String ticketUrl = null;
if (prNum != null) {
PullRequest pullReq = gitHubConnIgnited.getPullRequest(prNum);
if (pullReq != null && pullReq.getTitle() != null) {
prUrl = pullReq.htmlUrl();
-
- ticketFullName = TcBotTriggerAndSignOffService.getTicketFullName(pullReq, ticketPrefix);
}
}
- else
- ticketFullName = TcBotTriggerAndSignOffService.prLessTicket(branchName, ticketPrefix, tcIgnited);
if (!Strings.isNullOrEmpty(ticketFullName))
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 17624a5..5de0f23 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
@@ -64,7 +64,7 @@ import org.apache.ignite.ci.jira.pure.IJiraIntegration;
if (gitHubConn.isGitTokenAvailable())
javaFlags |= GITHUB_FLAG;
- if (jiraIntegration.isJiraTokenAvailable())
+ if (jiraIntegration.config().isJiraTokenAvailable())
javaFlags |= JIRA_FLAG;
}
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetBuildLog.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetBuildLog.java
index 0a141d9..03e00fb 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetBuildLog.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetBuildLog.java
@@ -64,8 +64,7 @@ public class GetBuildLog {
@PermitAll
public Response getThreadDump(
@QueryParam(SERVER_ID) String srvId,
- @QueryParam(BUILD_NO) Integer buildNo,
- @Deprecated @QueryParam(FILE_IDX) Integer fileIdx) {
+ @QueryParam(BUILD_NO) Integer buildNo) {
ITcServerProvider helper = CtxListener.getInjector(ctx).getInstance(ITcServerProvider.class);
ITcAnalytics srv = helper.server(srvId, null);
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetTrackedBranches.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetTrackedBranches.java
index 1d20811..ea62194 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetTrackedBranches.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/GetTrackedBranches.java
@@ -18,6 +18,7 @@
package org.apache.ignite.ci.web.rest;
import com.google.common.base.Strings;
+import com.google.inject.Injector;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -31,10 +32,10 @@ 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.HelperConfig;
import org.apache.ignite.ci.conf.ChainAtServer;
import org.apache.ignite.ci.tcbot.TcBotGeneralService;
import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
+import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
import org.apache.ignite.ci.user.ICredentialsProv;
import org.apache.ignite.ci.web.CtxListener;
import org.apache.ignite.ci.web.model.Version;
@@ -76,7 +77,9 @@ public class GetTrackedBranches {
public Set<ChainAtServer> getSuites(@Nullable @QueryParam("server") String srvId) {
final ICredentialsProv prov = ICredentialsProv.get(req);
- return HelperConfig.getTrackedBranches()
+ Injector injector = CtxListener.getInjector(ctx);
+ ITcBotConfig cfg = injector.getInstance(ITcBotConfig.class);
+ return cfg.getTrackedBranches()
.getSuitesUnique()
.stream()
.filter(chainAtSrv ->
@@ -86,16 +89,26 @@ public class GetTrackedBranches {
.collect(Collectors.toSet());
}
+ /**
+ * Return all servers registered in TC Bot config: Both from tracked branches and from
+ */
@GET
@Path("getServerIds")
public Set<String> getServerIds() {
final ICredentialsProv prov = ICredentialsProv.get(req);
- return HelperConfig.getTrackedBranches()
- .getServerIds()
- .stream()
- .filter(prov::hasAccess)
- .collect(Collectors.toSet());
+ Injector injector = CtxListener.getInjector(ctx);
+ ITcBotConfig cfg = injector.getInstance(ITcBotConfig.class);
+
+ ITeamcityIgnitedProvider tcProv = injector.getInstance(ITeamcityIgnitedProvider.class);
+ return cfg.getServerIds()
+ .stream()
+ .filter(srvId ->
+ {
+ return tcProv.hasAccess(srvId, prov);
+
+ })
+ .collect(Collectors.toSet());
}
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuilds.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuilds.java
index 5f4031c..5c527ba 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuilds.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/TriggerBuilds.java
@@ -125,7 +125,7 @@ public class TriggerBuilds {
IGitHubConnection gh = injector.getInstance(IGitHubConnectionProvider.class).server(srvId);
- return new ServerIntegrationLinks(srvId, gh.gitApiUrl(), jira.getJiraApiUrl());
+ return new ServerIntegrationLinks(srvId, gh.gitApiUrl(), jira.restApiUrl());
}).filter(Objects::nonNull).collect(Collectors.toSet());
}
}
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/exception/ServiceUnauthorizedException.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/exception/ServiceUnauthorizedException.java
index f59be5d..80e4b5a 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/exception/ServiceUnauthorizedException.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/exception/ServiceUnauthorizedException.java
@@ -32,8 +32,8 @@ public class ServiceUnauthorizedException extends RuntimeException
public ServiceUnauthorizedException() {
}
- public static ServiceUnauthorizedException noCreds(String serverId) {
- return new ServiceUnauthorizedException("Service [" + serverId + "] is not available for current user");
+ public static ServiceUnauthorizedException noCreds(String srvId) {
+ return new ServiceUnauthorizedException("Service [" + srvId + "] is not available for current user");
}
@Override
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/login/Login.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/login/Login.java
index f6f62d1..f508aeb 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/login/Login.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/login/Login.java
@@ -58,7 +58,7 @@ public class Login {
Injector injector = CtxListener.getInjector(ctx);
ITcBotConfig tcBotCfg = injector.getInstance(ITcBotConfig.class);
- String srvId = tcBotCfg.primaryServerId();
+ String srvId = tcBotCfg.primaryServerCode();
String host = injector.getInstance(ITeamcityIgnitedProvider.class).server(srvId, null).host();
return new ServerDataResponse(host);
}
@@ -76,11 +76,10 @@ public class Login {
final ITcLogin tcLogin = injector.getInstance(ITcLogin.class);
IUserStorage users = injector.getInstance(IUserStorage.class);
- String primarySrvId = cfg.primaryServerId();
+ String primarySrvCode = cfg.primaryServerCode();
try {
- return doLogin(username, pwd, users, primarySrvId,
- cfg.getServerIds(), tcLogin);
+ return doLogin(username, pwd, users, primarySrvCode, cfg.getServerIds(), tcLogin);
} catch (Exception e) {
e.printStackTrace();
throw e;
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 7745e73..9a7bbba 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,7 +17,6 @@
package org.apache.ignite.ci.web.rest.pr;
-import com.google.common.base.Preconditions;
import com.google.inject.Injector;
import javax.annotation.Nonnull;
import javax.servlet.ServletContext;
@@ -142,7 +141,7 @@ public class GetPrTestFailures {
PullRequest pr;
try {
- Integer prId = IGitHubConnection.convertBranchToId(branchForTc);
+ Integer prId = IGitHubConnection.convertBranchToPrId(branchForTc);
if (prId == null)
return "Invalid TC branch name: [" + branchForTc + "]";
diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java
index de1d0a8..e8a9202 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/rest/tracked/GetTrackedBranchTestResults.java
@@ -42,7 +42,6 @@ import org.apache.ignite.internal.util.typedef.F;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import static org.apache.ignite.ci.tcbot.conf.ITcBotConfig.DEFAULT_SERVER_ID;
import static org.apache.ignite.ci.teamcity.ignited.TeamcityIgnitedImpl.DEFAULT_PROJECT_ID;
@Path(GetTrackedBranchTestResults.TRACKED)
@@ -156,7 +155,7 @@ public class GetTrackedBranchTestResults {
ITcBotConfig cfg = CtxListener.getInjector(ctx).getInstance(ITcBotConfig.class);
if (F.isEmpty(srvId))
- srvId = DEFAULT_SERVER_ID;
+ srvId = cfg.primaryServerCode();
if (F.isEmpty(projectId))
projectId = DEFAULT_PROJECT_ID;
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 f7bfa78..a3d94cb 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
@@ -16,6 +16,7 @@
*/
package org.apache.ignite.ci.web.rest.visa;
+import com.google.inject.Injector;
import java.util.Collection;
import java.util.List;
import java.util.Set;
@@ -34,6 +35,7 @@ import org.apache.ignite.ci.tcbot.visa.ContributionToCheck;
import org.apache.ignite.ci.tcbot.visa.CurrentVisaStatus;
import org.apache.ignite.ci.tcbot.visa.TcBotTriggerAndSignOffService;
import org.apache.ignite.ci.tcbot.visa.VisaStatus;
+import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
import org.apache.ignite.ci.user.ICredentialsProv;
import org.apache.ignite.ci.web.CtxListener;
import org.apache.ignite.ci.web.model.ContributionKey;
@@ -82,11 +84,11 @@ public class TcBotVisaService {
public List<ContributionToCheck> contributions(@Nullable @QueryParam("serverId") String srvId) {
ICredentialsProv credsProv = ICredentialsProv.get(req);
- if (!credsProv.hasAccess(srvId))
- throw ServiceUnauthorizedException.noCreds(srvId);
+ Injector injector = CtxListener.getInjector(ctx);
- return CtxListener.getInjector(ctx)
- .getInstance(TcBotTriggerAndSignOffService.class).getContributionsToCheck(srvId, credsProv);
+ injector.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvId, credsProv);
+
+ return injector.getInstance(TcBotTriggerAndSignOffService.class).getContributionsToCheck(srvId, credsProv);
}
@GET
@@ -94,11 +96,12 @@ public class TcBotVisaService {
public Set<ContributionCheckStatus> contributionStatus(@Nullable @QueryParam("serverId") String srvId,
@QueryParam("prId") String prId) {
ICredentialsProv prov = ICredentialsProv.get(req);
- if (!prov.hasAccess(srvId))
- throw ServiceUnauthorizedException.noCreds(srvId);
- return CtxListener.getInjector(ctx)
- .getInstance(TcBotTriggerAndSignOffService.class).contributionStatuses(srvId, prov, prId);
+ Injector injector = CtxListener.getInjector(ctx);
+
+ injector.getInstance(ITeamcityIgnitedProvider.class).checkAccess(srvId, prov);
+
+ return injector.getInstance(TcBotTriggerAndSignOffService.class).contributionStatuses(srvId, prov, prId);
}
@GET
diff --git a/ignite-tc-helper-web/src/main/webapp/js/prs-1.1.js b/ignite-tc-helper-web/src/main/webapp/js/prs-1.1.js
index 2ecb6fc..1328764 100644
--- a/ignite-tc-helper-web/src/main/webapp/js/prs-1.1.js
+++ b/ignite-tc-helper-web/src/main/webapp/js/prs-1.1.js
@@ -17,7 +17,7 @@ function drawTable(srvId, element) {
" </table>\n");
}
-function requestTableForServer(srvId, suiteIdIgnored, element) {
+function requestTableForServer(srvId, element) {
let tableId = "serverContributions-" + srvId;
diff --git a/ignite-tc-helper-web/src/main/webapp/prs.html b/ignite-tc-helper-web/src/main/webapp/prs.html
index 1eabc89..6989a00 100644
--- a/ignite-tc-helper-web/src/main/webapp/prs.html
+++ b/ignite-tc-helper-web/src/main/webapp/prs.html
@@ -61,9 +61,7 @@
function showServerContribTabs(result) {
const processed = new Set();
- for (let chainAtServer of result) {
- let serverId = chainAtServer.serverId;
-
+ for (let serverId of result) {
if (processed.has(serverId))
continue;
@@ -82,7 +80,7 @@
tabsInsertion.after("<div id=\"" + tabId + "\">" + "</div>");
- requestTableForServer(serverId, chainAtServer.suiteId, $(tabRef));
+ requestTableForServer(serverId, $(tabRef));
}
showTabs();
@@ -104,7 +102,14 @@
showSuitesForTeamCityRunData(result);
showFormAndSuitesForPrCheck(result);
showCommentJiraForm(result);
+ },
+ error: showErrInLoadStatus
+ });
+ $.ajax({
+ url: "rest/branches/getServerIds",
+ success: function(result) {
+ $("#loadStatus").html("");
showServerContribTabs(result);
},
error: showErrInLoadStatus
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java
index 77fd7c2..e4bfdec 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/MockBasedTcBotModule.java
@@ -17,11 +17,14 @@
package org.apache.ignite.ci.tcbot.chain;
-import com.google.common.base.Preconditions;
import com.google.inject.AbstractModule;
import com.google.inject.internal.SingletonScope;
+import java.io.File;
+import java.util.Properties;
+
+import org.apache.ignite.ci.HelperConfig;
import org.apache.ignite.ci.IAnalyticsEnabledTeamcity;
-import org.apache.ignite.ci.conf.BranchesTracked;
+import org.apache.ignite.ci.tcbot.conf.BranchesTracked;
import org.apache.ignite.ci.github.PullRequest;
import org.apache.ignite.ci.github.ignited.IGitHubConnIgnited;
import org.apache.ignite.ci.github.ignited.IGitHubConnIgnitedProvider;
@@ -29,7 +32,7 @@ import org.apache.ignite.ci.github.pure.IGitHubConnection;
import org.apache.ignite.ci.github.pure.IGitHubConnectionProvider;
import org.apache.ignite.ci.jira.pure.IJiraIntegration;
import org.apache.ignite.ci.jira.pure.IJiraIntegrationProvider;
-import org.apache.ignite.ci.tcbot.conf.ITcBotConfig;
+import org.apache.ignite.ci.tcbot.conf.*;
import org.apache.ignite.ci.tcbot.issue.IIssuesStorage;
import org.apache.ignite.ci.tcbot.user.IUserStorage;
import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
@@ -98,13 +101,35 @@ public class MockBasedTcBotModule extends AbstractModule {
bind(ITcServerProvider.class).toInstance(tcSrvOldProv);
bind(ITcBotConfig.class).toInstance(new ITcBotConfig() {
- @Override public String primaryServerId() {
- return ITcBotConfig.DEFAULT_SERVER_ID;
+ @Override public String primaryServerCode() {
+ return ITcBotConfig.DEFAULT_SERVER_CODE;
}
@Override public BranchesTracked getTrackedBranches() {
return tracked;
}
+
+ /** {@inheritDoc} */
+ @Override public ITcServerConfig getTeamcityConfig(String srvCode) {
+ return new TcServerConfig(srvCode, loadOldProps(srvCode));
+ }
+
+ @Override public IJiraServerConfig getJiraConfig(String srvCode) {
+ return new JiraServerConfig(srvCode, loadOldProps(srvCode));
+ }
+
+ @Override
+ public IGitHubConfig getGitConfig(String srvCode) {
+ return new GitHubConfig(srvCode, loadOldProps(srvCode));
+ }
+
+ private Properties loadOldProps(String srvCode) {
+ File workDir = HelperConfig.resolveWorkDir();
+
+ String cfgName = HelperConfig.prepareConfigName(srvCode);
+
+ return HelperConfig.loadAuthProperties(workDir, cfgName);
+ }
});
bind(IIssuesStorage.class).toInstance(Mockito.mock(IIssuesStorage.class));
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/TrackedBranchProcessorTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/TrackedBranchProcessorTest.java
index 3164e7d..87e35ed 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/TrackedBranchProcessorTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/chain/TrackedBranchProcessorTest.java
@@ -27,7 +27,7 @@ import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.ignite.ci.ITeamcity;
import org.apache.ignite.ci.conf.BranchTracked;
-import org.apache.ignite.ci.conf.BranchesTracked;
+import org.apache.ignite.ci.tcbot.conf.BranchesTracked;
import org.apache.ignite.ci.conf.ChainAtServerTracked;
import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/issue/IssueDetectorTest.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/issue/IssueDetectorTest.java
index a1b6f59..d519ef4 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/issue/IssueDetectorTest.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/tcbot/issue/IssueDetectorTest.java
@@ -29,7 +29,7 @@ import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.ignite.ci.ITeamcity;
import org.apache.ignite.ci.conf.BranchTracked;
-import org.apache.ignite.ci.conf.BranchesTracked;
+import org.apache.ignite.ci.tcbot.conf.BranchesTracked;
import org.apache.ignite.ci.conf.ChainAtServerTracked;
import org.apache.ignite.ci.tcbot.chain.MockBasedTcBotModule;
import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrenceFull;
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedMock.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedMock.java
index b5b1ace..159f336 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedMock.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedMock.java
@@ -116,7 +116,7 @@ public class TeamcityIgnitedMock {
return runHistCompacted;
});
- when(tcIgnited.gitBranchPrefix()).thenReturn("ignite-");
+ // when(tcIgnited.gitBranchPrefix()).thenReturn("ignite-");
return tcIgnited;
}
diff --git a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedProviderMock.java b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedProviderMock.java
index f9f0eca..d484a13 100644
--- a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedProviderMock.java
+++ b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedProviderMock.java
@@ -17,6 +17,7 @@
package org.apache.ignite.ci.teamcity.ignited;
+import javax.annotation.Nullable;
import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
import org.apache.ignite.ci.user.ICredentialsProv;
@@ -25,6 +26,7 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class TeamcityIgnitedProviderMock implements ITeamcityIgnitedProvider {
+ /** Compactor. */
@Inject IStringCompactor compactor;
private Map<String, Map<Integer, FatBuildCompacted>> tcBuildsData = new ConcurrentHashMap<>();
@@ -33,8 +35,13 @@ public class TeamcityIgnitedProviderMock implements ITeamcityIgnitedProvider {
tcBuildsData.put(srvId, apacheBuilds);
}
- @Override
- public ITeamcityIgnited server(String srvId, ICredentialsProv prov) {
+ /** {@inheritDoc} */
+ @Override public boolean hasAccess(String srvId, @Nullable ICredentialsProv prov) {
+ return prov.hasAccess(srvId);
+ }
+
+ /** {@inheritDoc} */
+ @Override public ITeamcityIgnited server(String srvId, ICredentialsProv prov) {
final Map<Integer, FatBuildCompacted> integerFatBuildCompactedMap = tcBuildsData.get(srvId);
return TeamcityIgnitedMock.getMutableMapTeamcityIgnited(integerFatBuildCompactedMap, compactor);