Skip to content
Permalink
Browse files
Triggering fix: older master builds were not triggered because build …
…type ID is not checked during check queue job
  • Loading branch information
dspavlov committed Aug 16, 2019
1 parent e2c8ab9 commit 9d1dc6a7e405d84b93ccfce0d571db13c8931c6e
Showing 11 changed files with 152 additions and 93 deletions.
@@ -17,9 +17,23 @@

package org.apache.ignite.ci.jobs;

import com.google.common.base.Strings;
import java.text.MessageFormat;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.inject.Inject;
import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
import org.apache.ignite.ci.user.ITcBotUserCreds;
import org.apache.ignite.internal.util.typedef.T2;
import org.apache.ignite.tcbot.common.exeption.ExceptionUtil;
import org.apache.ignite.tcbot.common.interceptor.AutoProfiling;
import org.apache.ignite.tcbot.common.interceptor.MonitoredTask;
@@ -36,13 +50,6 @@
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;
import java.util.stream.Stream;

/**
* Trigger build if half of agents are available and there is no self-triggered builds in build queue.
*/
@@ -94,7 +101,7 @@ public void init(ITcBotUserCreds creds) {
/** */
@SuppressWarnings({"WeakerAccess", "UnusedReturnValue"})
@AutoProfiling
@MonitoredTask(name = "Check Servers Queue")
@MonitoredTask(name = "Check Servers Queue (Triggering)")
protected String runEx() {
if (Boolean.valueOf(System.getProperty(AUTO_TRIGGERING_BUILD_DISABLED))) {
final String msg = "Automatic build triggering was disabled.";
@@ -144,7 +151,7 @@ protected String runEx() {
*/
@SuppressWarnings({"WeakerAccess", "UnusedReturnValue"})
@AutoProfiling
@MonitoredTask(name = "Check Server Queue", nameExtArgIndex = 0)
@MonitoredTask(name = "Check Server Queue (Triggering)", nameExtArgIndex = 0)
protected String checkQueue(String srvCode, List<ITrackedChain> chains) {
ITeamcityIgnited tcIgn = tcIgnitedProv.server(srvCode, creds);

@@ -180,32 +187,34 @@ protected String checkQueue(String srvCode, List<ITrackedChain> chains) {
if (!Objects.equals(chain.serverCode(), srvCode))
continue;

String result = checkIfChainTriggerable(chain.serverCode(), chain.tcSuiteId(), chain.tcBranch(), tcIgn, selfLogin, chain);
String chainRes = checkIfChainTriggerable(chain.serverCode(), chain.tcSuiteId(), chain.tcBranch(), tcIgn, selfLogin, chain, agentStatus);

res.append(result).append("; ");
res.append(chainRes).append("; ");
}

return res.toString();
}

@SuppressWarnings("WeakerAccess")
@MonitoredTask(name = "Check Server Queue", nameExtArgsIndexes = {0, 1, 2})
protected String checkIfChainTriggerable(String serverCode,
String buildTypeId,
String tcBranch,
ITeamcityIgnited tcIgn,
String selfLogin,
ITrackedChain chain) {
@MonitoredTask(name = "Check Server Queue (Triggering)", nameExtArgsIndexes = {0, 1, 2})
protected String checkIfChainTriggerable(String srvCode,
String buildTypeId,
String tcBranch,
ITeamcityIgnited tcIgn,
String selfLogin,
ITrackedChain chain,
String agentStatus) {
List<BuildRefCompacted> buildsForBr = tcIgn.getQueuedBuildsCompacted(tcBranch);

for (BuildRefCompacted refComp : buildsForBr) {
Integer buildId = refComp.getId();
if (buildId == null)
continue; // should not occur;

final FatBuildCompacted fatBuild = tcIgn.getFatBuild(buildId);
final Build build = fatBuild.toBuild(compactor);
final Triggered triggered = build.getTriggered();
FatBuildCompacted fatBuild = tcIgn.getFatBuild(buildId);

Build build = fatBuild.toBuild(compactor);
Triggered triggered = build.getTriggered();

if (triggered == null) {
logger.info("Unable to get triggering info for queued build {} (type={}).", buildId, build.buildTypeId);
@@ -221,13 +230,21 @@ protected String checkIfChainTriggerable(String serverCode,
continue;
}

String buildTypeIdExisting = build.buildTypeId();
if (buildTypeIdExisting == null) {
logger.info("Unable to get buildTypeId for queued build {} (type={}).", buildId, build.buildTypeId);

continue;
}

String login = user.username;

if (selfLogin.equalsIgnoreCase(login)) {
final String msg
= MessageFormat.format("Queued build {0} was early triggered " +
"(user {1}, branch {2}, suite {3})." +
" Will not start new build.", buildId, login, tcBranch, build.buildTypeId);
if (selfLogin.equalsIgnoreCase(login)
&& buildTypeIdExisting.trim().equals(Strings.nullToEmpty(buildTypeId).trim())) {
String msg
= MessageFormat.format("Queued build {0} was early triggered " +
"(user {1}, branch {2}, suite {3})." +
" Will not start new build.", Integer.toString(buildId), login, tcBranch, buildTypeIdExisting);

logger.info(msg);

@@ -238,17 +255,16 @@ protected String checkIfChainTriggerable(String serverCode,
long curr = System.currentTimeMillis();
long delay = chain.triggerBuildQuietPeriod();

long minsPassed = -1;
if (delay > 0) {
Long lastStart = startTimes.get(chain);

long minsPassed;

if (lastStart != null &&
(minsPassed = TimeUnit.MILLISECONDS.toMinutes(curr - lastStart)) < delay) {

final String msg = MessageFormat.format("Skip triggering build, timeout has not expired " +
"(server={0}, suite={1}, branch={2}, delay={3} mins, passed={4} mins)",
serverCode, buildTypeId, tcBranch,
srvCode, buildTypeId, tcBranch,
chain.triggerBuildQuietPeriod(), minsPassed);
logger.info(msg);

@@ -258,9 +274,20 @@ protected String checkIfChainTriggerable(String serverCode,

startTimes.put(chain, curr);

tcIgn.triggerBuild(buildTypeId, tcBranch, true, false, chain.generateBuildParameters());
StringBuilder trigComment = new StringBuilder();
trigComment.append("Scheduled run ");
trigComment.append(agentStatus);
if (minsPassed > 0)
trigComment.append(" Since last build triggering: ").append(Duration.ofMinutes(minsPassed));

T2<Build, Set<Integer>> buildAndIds = tcIgn.triggerBuild(buildTypeId, tcBranch, true, false,
chain.generateBuildParameters(),
true,
trigComment.toString());

Build build = buildAndIds.get1();

return buildTypeId + " " + tcBranch + " triggered; ";
return "Build id " + build.getId() + " " + tcBranch + " for " + buildTypeId + " triggered; ";
}

/**
@@ -62,7 +62,7 @@ public static void main(String[] args) throws Exception {
String buildTypeIdAllP = "id8xIgniteGridGainTestsJava8_RunAll";
// buildTypeIdAll="IgniteTests24Java8_Queries1";

helper.triggerBuild(buildTypeIdAll, branchName, true, false, Collections.emptyMap());
helper.triggerBuild(buildTypeIdAll, branchName, true, false, Collections.emptyMap(), null);
}
}

@@ -28,6 +28,7 @@
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
@@ -56,6 +57,7 @@
import org.apache.ignite.githubignited.IGitHubConnIgnited;
import org.apache.ignite.githubignited.IGitHubConnIgnitedProvider;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.T2;
import org.apache.ignite.jiraignited.IJiraIgnited;
import org.apache.ignite.jiraignited.IJiraIgnitedProvider;
import org.apache.ignite.jiraservice.Ticket;
@@ -65,8 +67,6 @@
import org.apache.ignite.tcbot.engine.conf.ITcBotConfig;
import org.apache.ignite.tcbot.engine.pr.BranchTicketMatcher;
import org.apache.ignite.tcbot.engine.pr.PrChainsProcessor;
import org.apache.ignite.tcbot.engine.ui.DsSuiteUi;
import org.apache.ignite.tcbot.engine.ui.DsTestFailureUi;
import org.apache.ignite.tcbot.engine.ui.ShortSuiteUi;
import org.apache.ignite.tcbot.engine.ui.ShortTestFailureUi;
import org.apache.ignite.tcbot.persistence.IStringCompactor;
@@ -291,9 +291,16 @@ private void insertTicketStatus(Set<MuteInfo> mutes, Collection<Ticket> tickets,

//todo consult if there are change differences here https://ci.ignite.apache.org/app/rest/changes?locator=buildType:(id:IgniteTests24Java8_Cache7),pending:true,branch:pull%2F6224%2Fhead
Build[] builds = new Build[suiteIds.length];
Set<Integer> buildidsToSync = new HashSet<>();

for (int i = 0; i < suiteIds.length; i++)
builds[i] = teamcity.triggerBuild(suiteIds[i], branchForTc, false, top != null && top, new HashMap<String, Object>());
for (int i = 0; i < suiteIds.length; i++) {
T2<Build, Set<Integer>> objects = teamcity.triggerBuild(suiteIds[i], branchForTc, false, top != null && top, new HashMap<>(),
false, "");
buildidsToSync.addAll(objects.get2());
builds[i] = objects.get1();
}

teamcity.fastBuildsSync(buildidsToSync);

if (observe != null && observe)
jiraRes += observeJira(srvCodeOrAlias, branchForTc, ticketId, prov, parentSuiteId, baseBranchForTc, builds);
@@ -28,7 +28,7 @@
public static final String GITHUB_REF = "https://github.com/apache/ignite-teamcity-bot";

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

/** Java version, where Web App is running. */
public String javaVer;
@@ -204,7 +204,7 @@ protected String issuesToDefects() {
Stream<Issue> stream = issuesStorage.allIssues();

//todo make property how old issues can be considered as configuration parameter
long minIssueTs = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(9);
long minIssueTs = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(11);

//todo not so good to to call init() twice
fatBuildDao.init();
@@ -69,7 +69,7 @@ public class ChainAtServerTracked extends ChainAtServer implements ITrackedChain
/**
* @return base (etalon) branch in TC identification t builds
*/
@Nonnull public Optional<String> tcBaseBranch() {
@Override @Nonnull public Optional<String> tcBaseBranch() {
if (Strings.isNullOrEmpty(baseBranchForTc))
return Optional.empty();

@@ -97,29 +97,25 @@ public class ChainAtServerTracked extends ChainAtServer implements ITrackedChain
return Objects.hash(super.hashCode(), branchForRest, baseBranchForTc, triggerBuild, triggerBuildQuietPeriod, triggerParameters);
}

/**
* @return {@code True} If automatic build triggering enabled.
*/
public boolean triggerBuild() {
/** {@inheritDoc} */
@Override public boolean triggerBuild() {
return triggerBuild == null ? false : triggerBuild;
}

/**
* @return Quiet period in minutes between triggering builds or zero if period is not set and should be ignored.
*/
public int triggerBuildQuietPeriod() {
/** {@inheritDoc} */
@Override public int triggerBuildQuietPeriod() {
return triggerBuildQuietPeriod == null ? 0 : triggerBuildQuietPeriod;
}

@Override
public String tcSuiteId() {
/** {@inheritDoc} */
@Override public String tcSuiteId() {
return suiteId;
}

/**
* @return Map with parameter values for current run.
*/
@Nonnull public Map<String, Object> generateBuildParameters() {
@Override @Nonnull public Map<String, Object> generateBuildParameters() {
if (triggerParameters == null || triggerParameters.isEmpty())
return Collections.emptyMap();

@@ -145,17 +141,13 @@ public Stream<String> buildParametersKeys() {
return triggerParameters.stream().map(BuildParameterSpec::name);
}

@Override
public String tcBranch() {
/** {@inheritDoc} */
@Override public String tcBranch() {
return branchForRest;
}

/**
* @return Server ID to access configs within IDataSourceCfgSupplier.
*/
@Override
public String serverCode() {
/** {@inheritDoc} */
@Override public String serverCode() {
return serverId;
}

}
@@ -24,14 +24,17 @@
*
*/
public interface ITrackedChain {
/**
* @return Server Code to access configs within IDataSourceCfgSupplier.
*/
public String serverCode();

public String tcBranch();

@Nonnull public Optional<String> tcBaseBranch();

/**
* @return trigger build quiet period, milliseconds.
* @return Quiet period in minutes between triggering builds or zero if period is not set and should be ignored.
*/
public int triggerBuildQuietPeriod();

@@ -40,5 +43,8 @@ public interface ITrackedChain {

public String tcSuiteId();

/**
* @return {@code True} If automatic build triggering enabled.
*/
public boolean triggerBuild();
}
@@ -33,6 +33,7 @@
import org.apache.ignite.ci.teamcity.ignited.change.ChangeCompacted;
import org.apache.ignite.ci.teamcity.ignited.change.RevisionCompacted;
import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
import org.apache.ignite.internal.util.typedef.T2;
import org.apache.ignite.tcbot.common.conf.ITcServerConfig;
import org.apache.ignite.tcignited.history.IRunHistory;
import org.apache.ignite.tcignited.history.ISuiteRunHistory;
@@ -101,17 +102,23 @@ public List<BuildRefCompacted> getFinishedBuildsCompacted(

/**
* Trigger build. Enforces TC Bot to load all builds related to this triggered one.
*
* @param buildTypeId Build type identifier.
* @param branchName Branch name.
* @param cleanRebuild Rebuild all dependencies.
* @param queueAtTop Put at the top of the build queue.
* @param buildParms addtitional build parameters, for example Java home or test suite. Use
* * <code>put("testSuite", "org.apache.ignite.spi.discovery.tcp.ipfinder.elb.TcpDiscoveryElbIpFinderSelfTest");</code>
* * to specify test suite to run.
* * <code>put("testSuite", "org.apache.ignite.spi.discovery.tcp.ipfinder.elb.TcpDiscoveryElbIpFinderSelfTest");</code>
* @param actualizeReferences enforce loading of triggered builds from TC now. Otherwise, return these IDS.
* @param freeTextComments some additional comments to be added to build (chain).
*/
public T2<Build, Set<Integer>> triggerBuild(String buildTypeId, String branchName, boolean cleanRebuild, boolean queueAtTop,
Map<String, Object> buildParms, boolean actualizeReferences, @Nullable String freeTextComments);

/**
* Runs synchronization of provided builds.
* @param collect Collect.
*/
public Build triggerBuild(String buildTypeId, String branchName, boolean cleanRebuild, boolean queueAtTop,
Map<String, Object> buildParms);
public void fastBuildsSync(Set<Integer> collect);

/**
* @param srvId Server id.

0 comments on commit 9d1dc6a

Please sign in to comment.