| /* |
| * 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.chain; |
| |
| import com.google.common.base.Strings; |
| import java.util.List; |
| import java.util.Objects; |
| import java.util.concurrent.atomic.AtomicInteger; |
| import java.util.stream.Collectors; |
| import javax.inject.Inject; |
| import org.apache.ignite.ci.IAnalyticsEnabledTeamcity; |
| import org.apache.ignite.ci.ITeamcity; |
| import org.apache.ignite.ci.analysis.FullChainRunCtx; |
| import org.apache.ignite.ci.analysis.SuiteInBranch; |
| import org.apache.ignite.ci.analysis.TestInBranch; |
| import org.apache.ignite.ci.analysis.mode.LatestRebuildMode; |
| import org.apache.ignite.ci.analysis.mode.ProcessLogsMode; |
| import org.apache.ignite.ci.di.AutoProfiling; |
| import org.apache.ignite.ci.github.ignited.IGitHubConnIgnited; |
| import org.apache.ignite.ci.github.ignited.IGitHubConnIgnitedProvider; |
| import org.apache.ignite.ci.github.pure.IGitHubConnectionProvider; |
| import org.apache.ignite.ci.jira.ignited.IJiraIgnited; |
| import org.apache.ignite.ci.jira.ignited.IJiraIgnitedProvider; |
| import org.apache.ignite.ci.tcbot.visa.BranchTicketMatcher; |
| import org.apache.ignite.ci.teamcity.ignited.IRunHistory; |
| import org.apache.ignite.ci.teamcity.ignited.IStringCompactor; |
| import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited; |
| import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider; |
| import org.apache.ignite.ci.teamcity.ignited.SyncMode; |
| import org.apache.ignite.ci.teamcity.ignited.runhist.RunHistSync; |
| import org.apache.ignite.ci.teamcity.restcached.ITcServerProvider; |
| import org.apache.ignite.ci.user.ICredentialsProv; |
| import org.apache.ignite.ci.web.model.current.ChainAtServerCurrentStatus; |
| import org.apache.ignite.ci.web.model.current.SuiteCurrentStatus; |
| import org.apache.ignite.ci.web.model.current.TestFailure; |
| import org.apache.ignite.ci.web.model.current.TestFailuresSummary; |
| import org.apache.ignite.ci.web.rest.parms.FullQueryParams; |
| import org.jetbrains.annotations.Nullable; |
| |
| /** |
| * Process pull request/untracked branch chain at particular server. |
| */ |
| public class PrChainsProcessor { |
| /** Build chain processor. */ |
| @Inject private BuildChainProcessor buildChainProcessor; |
| |
| /** Tc server provider. */ |
| @Inject private ITcServerProvider tcSrvProvider; |
| |
| /** Tc server provider. */ |
| @Inject private ITeamcityIgnitedProvider tcIgnitedProvider; |
| |
| /** Git hub connection provider. */ |
| @Inject private IGitHubConnectionProvider gitHubConnProvider; |
| |
| /** */ |
| @Inject private IGitHubConnIgnitedProvider gitHubConnIgnitedProvider; |
| |
| /** */ |
| @Inject private IJiraIgnitedProvider jiraIgnProv; |
| |
| @Inject private BranchTicketMatcher ticketMatcher; |
| |
| @Inject private IStringCompactor compactor; |
| |
| /** |
| * @param creds Credentials. |
| * @param srvCode Server id. |
| * @param suiteId Suite id. |
| * @param branchForTc Branch name in TC identification. |
| * @param act Action. |
| * @param cnt Count. |
| * @param baseBranchForTc Base branch name in TC identification. |
| * @param checkAllLogs Check all logs |
| * @param mode TC Server Sync Mode |
| * @return Test failures summary. |
| */ |
| @AutoProfiling |
| public TestFailuresSummary getTestFailuresSummary( |
| ICredentialsProv creds, |
| String srvCode, |
| String suiteId, |
| String branchForTc, |
| String act, |
| Integer cnt, |
| @Nullable String baseBranchForTc, |
| @Nullable Boolean checkAllLogs, |
| SyncMode mode) { |
| final TestFailuresSummary res = new TestFailuresSummary(); |
| final AtomicInteger runningUpdates = new AtomicInteger(); |
| |
| //using here non persistent TC allows to skip update statistic |
| IAnalyticsEnabledTeamcity teamcity = tcSrvProvider.server(srvCode, creds); |
| ITeamcityIgnited tcIgnited = tcIgnitedProvider.server(srvCode, creds); |
| |
| IGitHubConnIgnited gitHubConnIgnited = gitHubConnIgnitedProvider.server(srvCode); |
| |
| IJiraIgnited jiraIntegration = jiraIgnProv.server(srvCode); |
| |
| res.setJavaFlags(teamcity, gitHubConnIgnited, jiraIntegration); |
| |
| LatestRebuildMode rebuild; |
| if (FullQueryParams.HISTORY.equals(act)) |
| rebuild = LatestRebuildMode.ALL; |
| else if (FullQueryParams.LATEST.equals(act)) |
| rebuild = LatestRebuildMode.LATEST; |
| else if (FullQueryParams.CHAIN.equals(act)) |
| rebuild = LatestRebuildMode.NONE; |
| else |
| rebuild = LatestRebuildMode.LATEST; |
| |
| int buildResMergeCnt; |
| if (rebuild == LatestRebuildMode.ALL) |
| buildResMergeCnt = cnt == null ? 10 : cnt; |
| else |
| buildResMergeCnt = 1; |
| |
| ProcessLogsMode logs; |
| if (buildResMergeCnt > 1) |
| logs = (checkAllLogs != null && checkAllLogs) ? ProcessLogsMode.ALL : ProcessLogsMode.DISABLED; |
| else |
| logs = (checkAllLogs != null && checkAllLogs) ? ProcessLogsMode.ALL : ProcessLogsMode.SUITE_NOT_COMPLETE; |
| |
| List<Integer> hist = tcIgnited.getLastNBuildsFromHistory(suiteId, branchForTc, buildResMergeCnt); |
| |
| String baseBranch = Strings.isNullOrEmpty(baseBranchForTc) ? ITeamcity.DEFAULT : baseBranchForTc; |
| |
| final FullChainRunCtx ctx = buildChainProcessor.loadFullChainContext(teamcity, |
| tcIgnited, |
| hist, |
| rebuild, |
| logs, |
| buildResMergeCnt == 1, |
| baseBranch, |
| mode); |
| |
| final ChainAtServerCurrentStatus chainStatus = new ChainAtServerCurrentStatus(teamcity.serverCode(), branchForTc); |
| |
| chainStatus.baseBranchForTc = baseBranch; |
| |
| if (ctx.isFakeStub()) |
| chainStatus.setBuildNotFound(true); |
| else { |
| int cnt0 = (int)ctx.getRunningUpdates().count(); |
| |
| if (cnt0 > 0) |
| runningUpdates.addAndGet(cnt0); |
| |
| //fail rate reference is always default (master) |
| chainStatus.initFromContext(tcIgnited, ctx, baseBranch, compactor); |
| |
| chainStatus.initJiraAndGitInfo(ticketMatcher, jiraIntegration, gitHubConnIgnited); |
| } |
| |
| res.addChainOnServer(chainStatus); |
| |
| res.postProcess(runningUpdates.get()); |
| |
| return res; |
| } |
| |
| /** |
| * @param buildTypeId Build type ID, for which visa was ordered. |
| * @param branchForTc Branch for TeamCity. |
| * @param srvId Server id. |
| * @param prov Credentials. |
| * @return List of suites with possible blockers. |
| */ |
| @Nullable public List<SuiteCurrentStatus> getBlockersSuitesStatuses(String buildTypeId, |
| String branchForTc, |
| String srvId, |
| ICredentialsProv prov) { |
| return getBlockersSuitesStatuses(buildTypeId, branchForTc, srvId, prov, SyncMode.RELOAD_QUEUED); |
| } |
| |
| @Nullable |
| public List<SuiteCurrentStatus> getBlockersSuitesStatuses(String buildTypeId, String branchForTc, String srvId, |
| ICredentialsProv prov, SyncMode syncMode) { |
| //using here non persistent TC allows to skip update statistic |
| IAnalyticsEnabledTeamcity teamcity = tcSrvProvider.server(srvId, prov); |
| ITeamcityIgnited tcIgnited = tcIgnitedProvider.server(srvId, prov); |
| |
| List<Integer> hist = tcIgnited.getLastNBuildsFromHistory(buildTypeId, branchForTc, 1); |
| |
| String baseBranch = ITeamcity.DEFAULT; |
| |
| final FullChainRunCtx ctx = buildChainProcessor.loadFullChainContext(teamcity, |
| tcIgnited, |
| hist, |
| LatestRebuildMode.LATEST, |
| ProcessLogsMode.SUITE_NOT_COMPLETE, |
| true, |
| baseBranch, |
| syncMode); |
| |
| if (ctx.isFakeStub()) |
| return null; |
| |
| return findBlockerFailures(ctx, tcIgnited, baseBranch); |
| } |
| |
| /** |
| * @return Failures for given server. |
| * @param fullChainRunCtx |
| * @param tcIgnited |
| * @param baseBranch |
| */ |
| //todo may avoid creation of UI model for simple comment. |
| private List<SuiteCurrentStatus> findBlockerFailures(FullChainRunCtx fullChainRunCtx, ITeamcityIgnited tcIgnited, |
| String baseBranch) { |
| return fullChainRunCtx |
| .failedChildSuites() |
| .map((ctx) -> { |
| String normalizedBaseBranch = RunHistSync.normalizeBranch(baseBranch); |
| IRunHistory statInBaseBranch = tcIgnited.getSuiteRunHist(new SuiteInBranch(ctx.suiteId(), normalizedBaseBranch)); |
| |
| String suiteComment = ctx.getPossibleBlockerComment(compactor, statInBaseBranch, tcIgnited.config()); |
| |
| List<TestFailure> failures = ctx.getFailedTests().stream().map(occurrence -> { |
| IRunHistory stat = tcIgnited.getTestRunHist(new TestInBranch(occurrence.getName(), normalizedBaseBranch)); |
| |
| String testBlockerComment = occurrence.getPossibleBlockerComment(stat); |
| |
| if (!Strings.isNullOrEmpty(testBlockerComment)) { |
| final TestFailure failure = new TestFailure(); |
| |
| failure.initFromOccurrence(occurrence, tcIgnited, ctx.projectId(), ctx.branchName(), baseBranch); |
| |
| return failure; |
| } |
| return null; |
| }).filter(Objects::nonNull).collect(Collectors.toList()); |
| |
| |
| // test failure based blockers and/or blocker found by suite results |
| if (!failures.isEmpty() || !Strings.isNullOrEmpty(suiteComment)) { |
| |
| SuiteCurrentStatus suiteUi = new SuiteCurrentStatus(); |
| suiteUi.testFailures = failures; |
| |
| suiteUi.initFromContext(tcIgnited, ctx, baseBranch, compactor, false); |
| |
| return suiteUi; |
| } |
| |
| return null; |
| }) |
| .filter(Objects::nonNull) |
| .collect(Collectors.toList()); |
| } |
| } |