package io.qameta.allure.bamboo; import com.atlassian.bamboo.build.BuildDefinition; import com.atlassian.bamboo.chains.Chain; import com.atlassian.bamboo.chains.ChainExecution; import com.atlassian.bamboo.chains.ChainResultsSummary; import com.atlassian.bamboo.chains.plugins.PostChainAction; import com.atlassian.bamboo.v2.build.BaseConfigurablePlugin; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.util.Map; import static com.google.common.io.Files.createTempDir; import static io.qameta.allure.bamboo.AllureBuildResult.allureBuildResult; import static io.qameta.allure.bamboo.util.ExceptionUtil.stackTraceToString; import static java.util.Optional.ofNullable; import static org.apache.commons.io.FileUtils.deleteQuietly; @SuppressWarnings("ConstantConditions") public class AllureBuildCompleteAction extends BaseConfigurablePlugin implements PostChainAction { private static final Logger LOGGER = LoggerFactory.getLogger(AllureBuildCompleteAction.class); private final AllureExecutableProvider allureExecutable; private final AllureSettingsManager settingsManager; private final AllureArtifactsManager artifactsManager; private final BambooExecutablesManager executablesManager; public AllureBuildCompleteAction(AllureExecutableProvider allureExecutable, AllureSettingsManager settingsManager, AllureArtifactsManager artifactsManager, BambooExecutablesManager executablesManager) { this.allureExecutable = allureExecutable; this.settingsManager = settingsManager; this.artifactsManager = artifactsManager; this.executablesManager = executablesManager; } @Override public void execute(@NotNull Chain chain, @NotNull ChainResultsSummary chainResultsSummary, @NotNull ChainExecution chainExecution) throws Exception { final BuildDefinition buildDef = chain.getBuildDefinition(); final AllureGlobalConfig globalConfig = settingsManager.getSettings(); final AllureBuildConfig buildConfig = AllureBuildConfig.fromContext(buildDef.getCustomConfiguration()); final boolean allureEnabled = buildConfig.isEnabled() || (!buildConfig.isEnabledSet() && globalConfig.isEnabledByDefault()); final boolean isEnabledForFailedOnly = buildConfig.isOnlyForFailed(); if (!allureEnabled || (isEnabledForFailedOnly && !chainResultsSummary.isFailed())) { return; } final File artifactsTempDir = createTempDir(); final File allureReportDir = new File(createTempDir(), "report"); final Map<String, String> customBuildData = chainResultsSummary.getCustomBuildData(); try { final String executable = ofNullable(buildConfig.getExecutable()).orElseGet(() -> { LOGGER.info("Allure executable has not been configured. Using default one!"); return executablesManager.getDefaultAllureExecutable().orElseThrow(() -> new RuntimeException("Could not find default Allure executable! Please configure plugin properly!")); }); LOGGER.info("Allure Report is enabled for {}", chain.getName()); LOGGER.info("Trying to get executable by name {} for {}", executable, chain.getName()); allureExecutable.provide(globalConfig, executable).map(allure -> { LOGGER.info("Starting artifacts downloading into {} for {}", artifactsTempDir.getPath(), chain.getName()); artifactsManager.downloadAllArtifactsTo(chainResultsSummary, artifactsTempDir); if (artifactsTempDir.list().length == 0) { allureBuildResult(false, "Build result does not have any uploaded artifacts!") .dumpToCustomData(customBuildData); } else { LOGGER.info("Starting allure generate into {} for {}", allureReportDir.getPath(), chain.getName()); final AllureGenerateResult genRes = allure.generate(artifactsTempDir.toPath(), allureReportDir.toPath()); if (!genRes.isContainsTestcases()) { allureBuildResult(false, "No Allure results found! Please ensure that build artifacts contain " + "Allure results!\nAllure generate output: \n" + genRes.getOutput()).dumpToCustomData(customBuildData); } else { LOGGER.info("Allure has been generated successfully for {}", chain.getName()); artifactsManager.uploadReportArtifacts(chain, chainResultsSummary, allureReportDir) .ifPresent(result -> result.dumpToCustomData(customBuildData)); } } return true; }).orElseThrow(() -> new RuntimeException("Failed to find Allure executable by name " + executable)); } catch (Exception e) { LOGGER.error("Failed to build allure report for {}", chain.getName(), e); allureBuildResult(false, stackTraceToString(e)).dumpToCustomData(customBuildData); } finally { deleteQuietly(artifactsTempDir); deleteQuietly(allureReportDir); } } }