From 0f07b1372d767895dd79a6e43f85774d3ea5618f Mon Sep 17 00:00:00 2001 From: Manuel Lara Date: Fri, 19 Aug 2022 16:31:16 -0300 Subject: [PATCH 01/15] > Bamboo v7+ Support > Historical Fixes > Allure binary download, unzip, and so on was updated > All libraries was updated to newer versions > Removed the error when you add the allure task to any plan (only a log message is shown) Signed-off-by: Manuel Lara --- appveyor.yml | 5 +- pom.xml | 26 ++++--- .../allure/bamboo/AllureArtifactsManager.java | 72 +++++++++---------- .../bamboo/AllureBuildCompleteAction.java | 21 +++--- .../bamboo/AllureBuildConfigurator.java | 3 +- .../bamboo/AllureCommandLineSupport.java | 5 +- .../qameta/allure/bamboo/AllureConstants.java | 1 + .../allure/bamboo/AllureDownloader.java | 33 ++++----- .../bamboo/AllureExecutableProvider.java | 4 +- .../allure/bamboo/AllureGlobalConfig.java | 21 ++++-- .../allure/bamboo/AllureReportServlet.java | 7 +- .../allure/bamboo/AllureReportTask.java | 3 +- .../allure/bamboo/AllureSettingsManager.java | 8 +-- .../bamboo/BambooExecutablesManager.java | 3 +- .../io/qameta/allure/bamboo/util/ZipUtil.java | 45 ++++++++++++ src/main/resources/allure-bamboo.properties | 2 +- .../bamboo/AllureCommandLineSupportTest.java | 5 +- .../allure/bamboo/AllureDownloaderTest.java | 10 ++- .../bamboo/AllureExecutableProviderTest.java | 5 +- .../allure/bamboo/AllureExecutableTest.java | 5 +- .../allure/bamboo/util/ExceptionUtilTest.java | 4 +- 21 files changed, 171 insertions(+), 117 deletions(-) create mode 100644 src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java diff --git a/appveyor.yml b/appveyor.yml index 901c738..f67e697 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,10 +14,11 @@ install: - ps: | Add-Type -AssemblyName System.IO.Compression.FileSystem if (!(Test-Path -Path "C:\maven" )) { - (new-object System.Net.WebClient).DownloadFile('http://www.us.apache.org/dist/maven/maven-3/3.2.5/binaries/apache-maven-3.2.5-bin.zip', 'C:\maven-bin.zip') + (new-object System.Net.WebClient).DownloadFile('https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip', 'C:\maven-bin.zip') [System.IO.Compression.ZipFile]::ExtractToDirectory("C:\maven-bin.zip", "C:\maven") } - - cmd: SET M2_HOME=C:\maven\apache-maven-3.2.5 + - cmd: SET M2_HOME=C:\maven\apache-maven-3.8.1 + - cmd: SET ATLAS_MVN=%M2_HOME%\bin\mvn - cmd: SET PATH=%M2_HOME%\bin;%JAVA_HOME%\bin;%PATH:C:\Ruby193\bin;=% - cmd: SET JAVA_OPTS=-XX:MaxPermSize=2g -Xmx4g - cmd: mvn --version diff --git a/pom.xml b/pom.xml index abda532..895062c 100644 --- a/pom.xml +++ b/pom.xml @@ -14,13 +14,16 @@ https://github.com/allure-framework - 8.0.3-89c970d65 - 6.9.1 + 8.0.2 + 7.1.4 ${bamboo.version} - 1.2.3 - 1.2.13 + 1.8 + 1.8 + + 2.0.2 + 2.1.7 ${project.groupId}.${project.artifactId} - 1.7.29 + 1.7.36 1.2.17 1.8 @@ -36,7 +39,7 @@ org.buildobjects jproc - 2.2.1 + 2.8.0 com.atlassian.bamboo @@ -53,7 +56,7 @@ net.lingala.zip4j zip4j - 1.3.3 + 2.11.1 org.slf4j @@ -94,13 +97,13 @@ junit junit - 4.12 + 4.13.2 test org.mockito mockito-core - 3.2.4 + 4.6.1 test @@ -127,11 +130,6 @@ commons-beanutils 1.9.4 - - commons-beanutils - commons-beanutils - 1.9.4 - net.sf.json-lib json-lib diff --git a/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java b/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java index bbe49f6..4f7ee1d 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java @@ -1,5 +1,6 @@ package io.qameta.allure.bamboo; +import com.atlassian.bamboo.ResultKey; import com.atlassian.bamboo.artifact.MutableArtifact; import com.atlassian.bamboo.artifact.MutableArtifactImpl; import com.atlassian.bamboo.build.BuildDefinition; @@ -19,16 +20,17 @@ import com.atlassian.bamboo.build.artifact.TrampolineArtifactFileData; import com.atlassian.bamboo.build.artifact.TrampolineUrlArtifactLinkDataProvider; import com.atlassian.bamboo.build.artifact.handlers.ArtifactHandlersService; -import com.atlassian.bamboo.chains.Chain; import com.atlassian.bamboo.chains.ChainResultsSummary; import com.atlassian.bamboo.chains.ChainStageResult; +import com.atlassian.bamboo.plan.PlanKeys; import com.atlassian.bamboo.plan.PlanResultKey; import com.atlassian.bamboo.plan.artifact.ArtifactDefinitionContextImpl; +import com.atlassian.bamboo.plan.cache.ImmutableChain; import com.atlassian.bamboo.plugin.BambooPluginUtils; -import com.atlassian.bamboo.plugin.descriptor.predicate.ConjunctionModuleDescriptorPredicate; import com.atlassian.bamboo.resultsummary.BuildResultsSummary; import com.atlassian.bamboo.resultsummary.ResultsSummaryManager; import com.atlassian.bamboo.security.SecureToken; +import com.atlassian.plugin.ModuleDescriptor; import com.atlassian.plugin.PluginAccessor; import com.atlassian.plugin.predicate.EnabledModulePredicate; import com.atlassian.plugin.predicate.ModuleOfClassPredicate; @@ -57,6 +59,7 @@ import java.util.Map; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Predicate; import java.util.stream.Collector; @@ -114,30 +117,29 @@ public AllureArtifactsManager(PluginAccessor pluginAccessor, ArtifactHandlersSer * @param planKeyString key for plan * @param buildNumber build number * @param filePath path of the artifact - * @return empty if cannot get artifact, url if possible + * @return empty if you cannot get artifact, url if possible */ Optional getArtifactUrl(final String planKeyString, final String buildNumber, final String filePath) { final BuildDefinition buildDefinition = buildDefinitionManager.getBuildDefinition(getPlanKey(planKeyString)); final Map artifactConfig = getArtifactHandlersConfig(buildDefinition); final PlanResultKey planResultKey = getPlanResultKey(planKeyString, parseInt(buildNumber)); - return ofNullable(resultsSummaryManager.getResultsSummary(planResultKey)).map(resultsSummary -> - getArtifactHandlerByClassName(fromCustomData(resultsSummary.getCustomBuildData()).getArtifactHandlerClass()) - .map(artifactHandler -> { - if (isAgentArtifactHandler(artifactHandler)) { - return getLocalStorageURL(planKeyString, buildNumber, filePath); - } - final ArtifactDefinitionContextImpl artifactDef = getAllureArtifactDef(); - return ofNullable(artifactHandler.getArtifactLinkDataProvider( - mutableArtifact(planResultKey, artifactDef.getName()), configProvider(artifactConfig) - )).map(linkProvider -> { - if (linkProvider instanceof TrampolineUrlArtifactLinkDataProvider) { - final TrampolineUrlArtifactLinkDataProvider urlLinkProvider = (TrampolineUrlArtifactLinkDataProvider) linkProvider; - urlLinkProvider.setPlanResultKey(planResultKey); - urlLinkProvider.setArtifactName(artifactDef.getName()); - } - return getArtifactFile(filePath, linkProvider); - }).orElse(null); - }).orElse(null)); + return ofNullable(resultsSummaryManager.getResultsSummary(planResultKey)).flatMap(resultsSummary -> getArtifactHandlerByClassName(fromCustomData(resultsSummary.getCustomBuildData()).getArtifactHandlerClass()) + .map(artifactHandler -> { + if (isAgentArtifactHandler(artifactHandler)) { + return getLocalStorageURL(planKeyString, buildNumber, filePath); + } + final ArtifactDefinitionContextImpl artifactDef = getAllureArtifactDef(); + return ofNullable(artifactHandler.getArtifactLinkDataProvider( + mutableArtifact(planResultKey, artifactDef.getName()), configProvider(artifactConfig) + )).map(linkProvider -> { + if (linkProvider instanceof TrampolineUrlArtifactLinkDataProvider) { + final TrampolineUrlArtifactLinkDataProvider urlLinkProvider = (TrampolineUrlArtifactLinkDataProvider) linkProvider; + urlLinkProvider.setPlanResultKey(planResultKey); + urlLinkProvider.setArtifactName(artifactDef.getName()); + } + return getArtifactFile(filePath, linkProvider); + }).orElse(null); + })); } @Nullable @@ -190,14 +192,14 @@ Collection downloadAllArtifactsTo(@NotNull ChainResultsSummary chainResult } /** - * Copy all of the build's artifacts for this build across to the builds artifact directory + * Copy all the build's artifacts for this build across to the builds artifact directory * * @param chain chain * @param summary results summary * @param reportDir directory of a report * @return empty if not applicable, result otherwise */ - Optional uploadReportArtifacts(@NotNull Chain chain, @NotNull ChainResultsSummary summary, File reportDir) { + Optional uploadReportArtifacts(@NotNull ImmutableChain chain, @NotNull ChainResultsSummary summary, File reportDir) { try { final ArtifactDefinitionContextImpl artifact = getAllureArtifactDef(); artifact.setLocation(""); @@ -230,7 +232,7 @@ Optional uploadReportArtifacts(@NotNull Chain chain, @NotNull @Override public ArtifactHandlerPublishingResult call() { try { - return artifactHandler.publish(summary.getPlanResultKey(), artifact, artifactPublishingConfig); + return artifactHandler.publish((ResultKey) summary.getPlanResultKey(), artifact, artifactPublishingConfig); } catch (final Exception e) { LOGGER.error("Failed to publish Allure Report using handler " + artifactHandler.getClass().getName(), e); return ArtifactHandlerPublishingResultImpl.failure(); @@ -264,7 +266,7 @@ private void downloadAllArtifactsTo(ArtifactLinkDataProvider dataProvider, File data = trampolineData.getDelegate(); if (data.getFileType().equals(ArtifactFileData.FileType.REGULAR_FILE)) { final String fileName = Paths.get(data.getName()).toFile().getName(); - copyURLToFile(new URL(data.getUrl()), Paths.get(tempDir.getPath(), fileName).toFile()); + copyURLToFile(new URL(requireNonNull(data.getUrl())), Paths.get(tempDir.getPath(), fileName).toFile()); } else { downloadAllArtifactsTo(dataProvider, tempDir, trampolineData.getTag()); } @@ -280,7 +282,8 @@ private void logAndThrow(Exception e, String message) { throw new RuntimeException(message, e); } - private void downloadAllArtifactsTo(FileSystemArtifactLinkDataProvider dataProvider, File tempDir) { + @SuppressWarnings("UnstableApiUsage") + private void downloadAllArtifactsTo(@NotNull FileSystemArtifactLinkDataProvider dataProvider, File tempDir) { ofNullable(dataProvider.getFile().listFiles()).map(Arrays::asList).ifPresent(list -> list.forEach(file -> { try { if (file.isFile()) { @@ -298,7 +301,7 @@ private void downloadAllArtifactsTo(FileSystemArtifactLinkDataProvider dataProvi @Nullable private String getArtifactFile(String filePath, ArtifactLinkDataProvider linkProvider) { if (linkProvider instanceof FileSystemArtifactLinkDataProvider) { - return linkProvider.getRootUrl() + return requireNonNull(linkProvider.getRootUrl()) .replaceFirst("BASE_URL", getBaseUrl().build().toString()) .replace("index.html", isEmpty(filePath) ? "index.html" : filePath); } else { @@ -344,6 +347,7 @@ private Map getArtifactHandlersConfig(BuildDefinition buildDefin final Map planCustomConfiguration = buildDefinition.getCustomConfiguration(); if (ArtifactHandlingUtils.isCustomArtifactHandlingConfigured(planCustomConfiguration)) { // This hacky way it's compatible with both Bamboo 5.x and Bamboo 6.x + //TODO is it compatible with 7.x?? final Collector, ?, Map> toMap = toMap(Map.Entry::getKey, Map.Entry::getValue); final Predicate> isArtifactHandler = e -> e.getKey().startsWith(ARTIFACT_HANDLERS_CONFIG_PREFIX); final Predicate> isNotHandlerSwitch = e -> SHARED_NON_SHARED_ONOFF_OPTION_NAME.values().stream().noneMatch(o -> e.getKey().endsWith(o)); @@ -358,12 +362,9 @@ private MutableArtifact mutableArtifact(PlanResultKey planResultKey, String name return new MutableArtifactImpl(name, planResultKey, null, false, 0L); } - private List getArtifactHandlers() { - final ConjunctionModuleDescriptorPredicate predicate = new ConjunctionModuleDescriptorPredicate<>(); - - predicate.append(new ModuleOfClassPredicate<>(ArtifactHandler.class)); - predicate.append(new EnabledModulePredicate<>()); + private List getArtifactHandlers() { + Predicate> predicate = new ModuleOfClassPredicate<>(ArtifactHandler.class).and(new EnabledModulePredicate()); return ImmutableList.copyOf(pluginAccessor.getModules(predicate)); } @@ -374,15 +375,14 @@ private boolean isAgentArtifactHandler(ArtifactHandler artifactHandler) { @SuppressWarnings("unchecked") private Optional getArtifactHandlerByClassName(String className) { - final ConjunctionModuleDescriptorPredicate predicate = new ConjunctionModuleDescriptorPredicate<>(); + AtomicReference>> predicate = new AtomicReference<>(); return ofNullable(className).map(clazz -> { final Class aClass; try { aClass = (Class) Class.forName(clazz); - predicate.append(new ModuleOfClassPredicate<>(aClass)); - predicate.append(new EnabledModulePredicate<>()); + predicate.set(new ModuleOfClassPredicate<>(aClass).and(new EnabledModulePredicate())); - return pluginAccessor.getModules(predicate).stream().findAny().orElse(null); + return pluginAccessor.getModules(predicate.get()).stream().findAny().orElse(null); } catch (ClassNotFoundException e) { LOGGER.error("Failed to find artifact handler for class name " + className, e); } diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java index 2a0ecf4..85bd7f0 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java @@ -1,14 +1,15 @@ 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.configuration.AdministrationConfiguration; +import com.atlassian.bamboo.plan.cache.ImmutableChain; import com.atlassian.bamboo.resultsummary.ResultsSummary; import com.atlassian.bamboo.resultsummary.ResultsSummaryManager; import com.atlassian.bamboo.v2.build.BaseConfigurablePlugin; +import com.atlassian.bonnie.search.summary.Summary; import com.atlassian.spring.container.ContainerManager; import io.qameta.allure.bamboo.info.AddExecutorInfo; import org.apache.commons.lang3.StringUtils; @@ -25,17 +26,13 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; +import java.util.*; 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.lang.String.format; -import static java.util.Arrays.*; +import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; import static org.apache.commons.io.FileUtils.deleteQuietly; import static org.codehaus.plexus.util.FileUtils.copyDirectory; @@ -67,7 +64,8 @@ public AllureBuildCompleteAction(AllureExecutableProvider allureExecutable, } @Override - public void execute(@NotNull Chain chain, @NotNull ChainResultsSummary chainResultsSummary, @NotNull ChainExecution chainExecution) throws Exception { + @SuppressWarnings("UnstableApiUsage") + public void execute(@NotNull ImmutableChain chain, @NotNull ChainResultsSummary chainResultsSummary, @NotNull ChainExecution chainExecution) { final BuildDefinition buildDef = chain.getBuildDefinition(); final AllureGlobalConfig globalConfig = settingsManager.getSettings(); final AllureBuildConfig buildConfig = AllureBuildConfig.fromContext(buildDef.getCustomConfiguration()); @@ -116,7 +114,7 @@ public void execute(@NotNull Chain chain, @NotNull ChainResultsSummary chainResu } } - private void prepareResults(List artifactsTempDirs, Chain chain, ChainExecution chainExecution) throws IOException, InterruptedException { + private void prepareResults(List artifactsTempDirs, @NotNull ImmutableChain chain, @NotNull ChainExecution chainExecution) { copyHistory(artifactsTempDirs, chain.getPlanKey().getKey(), chainExecution.getPlanResultKey().getBuildNumber()); addExecutorInfo(artifactsTempDirs, chain, chainExecution.getPlanResultKey().getBuildNumber()); } @@ -124,7 +122,8 @@ private void prepareResults(List artifactsTempDirs, Chain chain, ChainExec /** * Write the history file to results directory. */ - private void copyHistory(List artifactsTempDirs, String planKey, int buildNumber) { + @SuppressWarnings("UnstableApiUsage") + private void copyHistory(@NotNull List artifactsTempDirs, String planKey, int buildNumber) { final Path tmpDirToDownloadHistory = createTempDir().toPath(); getLastBuildNumberWithHistory(planKey, buildNumber) .ifPresent(buildId -> copyHistoryFiles(planKey, tmpDirToDownloadHistory, buildId)); @@ -190,7 +189,7 @@ private String getHistoryArtifactUrl(String fileName, String planKey, int buildI getBambooBaseUrl(), planKey, buildId, fileName); } - private void addExecutorInfo(List artifactsTempDirs, Chain chain, int buildNumber) throws IOException, InterruptedException { + private void addExecutorInfo(@NotNull List artifactsTempDirs, @NotNull ImmutableChain chain, int buildNumber) { final String rootUrl = getBambooBaseUrl(); final String buildName = chain.getBuildName(); final String buildUrl = String.format("%s/browse/%s-%s", rootUrl, chain.getPlanKey().getKey(), buildNumber); diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildConfigurator.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildConfigurator.java index 48f44ec..f4d1e14 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildConfigurator.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildConfigurator.java @@ -5,7 +5,6 @@ import com.atlassian.bamboo.plan.configuration.MiscellaneousPlanConfigurationPlugin; import com.atlassian.bamboo.utils.error.ErrorCollection; import com.atlassian.bamboo.v2.build.BaseConfigurablePlugin; -import com.atlassian.bamboo.v2.build.configuration.MiscellaneousBuildConfigurationPlugin; import com.atlassian.bamboo.ww2.actions.build.admin.create.BuildConfiguration; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; @@ -62,7 +61,7 @@ public void prepareConfigObject(@NotNull BuildConfiguration buildConfiguration) buildConfiguration.setProperty(ALLURE_CONFIG_FAILED_ONLY, TRUE); } if (buildConfiguration.getProperty(ALLURE_CONFIG_EXECUTABLE) == null) { - ofNullable(executablesManager).map(manager -> manager.getDefaultAllureExecutable().orElse(null)) + ofNullable(executablesManager).flatMap(BambooExecutablesManager::getDefaultAllureExecutable) .ifPresent(executable -> buildConfiguration.setProperty(ALLURE_CONFIG_EXECUTABLE, executable)); } } diff --git a/src/main/java/io/qameta/allure/bamboo/AllureCommandLineSupport.java b/src/main/java/io/qameta/allure/bamboo/AllureCommandLineSupport.java index d939bbb..11e601c 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureCommandLineSupport.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureCommandLineSupport.java @@ -3,6 +3,7 @@ import org.buildobjects.process.ProcBuilder; import org.jetbrains.annotations.NotNull; +import java.io.File; import java.nio.file.Paths; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -41,6 +42,8 @@ boolean isWindows() { } boolean hasCommand(String command) { - return Paths.get(command).toFile().exists(); + File cmdFile = Paths.get(command).toFile(); + // It needs to be sure that the command is a file + return cmdFile.exists() && cmdFile.isFile(); } } diff --git a/src/main/java/io/qameta/allure/bamboo/AllureConstants.java b/src/main/java/io/qameta/allure/bamboo/AllureConstants.java index 21fa404..4cae816 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureConstants.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureConstants.java @@ -36,6 +36,7 @@ final class AllureConstants { static String ALLURE_CONFIG_DOWNLOAD_ENABLED = "custom.allure.config.download.enabled"; static String ALLURE_CONFIG_ENABLED_BY_DEFAULT = "custom.allure.config.enabled.default"; static String ALLURE_CONFIG_DOWNLOAD_URL = "custom.allure.config.download.url"; + static String ALLURE_CONFIG_DOWNLOAD_CLI_URL = "custom.allure.config.download.cli.url"; static String ALLURE_CONFIG_LOCAL_STORAGE = "custom.allure.config.local.storage"; private AllureConstants() { diff --git a/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java b/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java index 0d28673..887a34d 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java @@ -1,26 +1,22 @@ package io.qameta.allure.bamboo; -import net.lingala.zip4j.core.ZipFile; -import net.lingala.zip4j.exception.ZipException; +import io.qameta.allure.bamboo.util.ZipUtil; +import org.apache.commons.compress.archivers.ArchiveException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.nio.file.*; import java.util.Optional; import static java.lang.Integer.getInteger; import static java.nio.file.Files.createTempFile; import static java.util.concurrent.TimeUnit.SECONDS; import static javax.ws.rs.core.UriBuilder.fromPath; -import static org.apache.commons.io.FileUtils.copyInputStreamToFile; import static org.apache.commons.io.FileUtils.deleteQuietly; import static org.apache.commons.io.FileUtils.moveDirectory; @@ -41,15 +37,16 @@ Optional downloadAndExtractAllureTo(String allureHomeDir, String version) LOGGER.info("Extracting file {} to {}...", zipFilePath, allureHomeDir); final String extractedDirName = "allure-" + version; final File homeDir = new File(allureHomeDir); - final Path extracteDir = zipFilePath.getParent(); - new ZipFile(zipFilePath.toFile()).extractAll(extracteDir.toString()); + final Path extractDir = zipFilePath.getParent(); + ZipUtil.unzip(zipFilePath, extractDir.toString()); + if (homeDir.exists()) { LOGGER.info("Directory " + homeDir + " already exists, removing it.."); deleteQuietly(homeDir); } - moveDirectory(extracteDir.resolve(extractedDirName).toFile(), homeDir); + moveDirectory(extractDir.resolve(extractedDirName).toFile(), homeDir); return Paths.get(allureHomeDir); - } catch (ZipException | IOException e) { + } catch (ArchiveException | IOException e) { LOGGER.error("Failed to download and extract Allure of version {} to dir {}", version, allureHomeDir, e); return null; } finally { @@ -73,13 +70,13 @@ private Optional downloadAllure(String version) { ((HttpURLConnection) connection).setInstanceFollowRedirects(true); connection.connect(); try (InputStream input = connection.getInputStream()) { - copyInputStreamToFile(input, downloadToFile.toFile()); + Files.copy(input, downloadToFile, StandardCopyOption.REPLACE_EXISTING); return Optional.of(downloadToFile); } } catch (Exception e) { LOGGER - .warn("Failed to download from {}. Root cause : {}. Trying with next url.", - url, e.getMessage()); + .warn("Failed to download from {}. Root cause : {}.", + url, e.toString()); } } } catch (Exception e) { @@ -89,13 +86,13 @@ private Optional downloadAllure(String version) { } private URL[] buildAllureDownloadUrls(String version) throws MalformedURLException { - URL oldUrl = fromPath(settingsManager.getSettings().getDownloadBaseUrl()) + URL gitUrl = fromPath(settingsManager.getSettings().getDownloadBaseUrl()) .path(version + "/" + "allure-" + version + ".zip") .build().toURL(); String binaryName = "allure-commandline"; - URL newUrl = fromPath(settingsManager.getSettings().getDownloadBaseUrl()) + URL mavenUrl = fromPath(settingsManager.getSettings().getDownloadCliBaseUrl()) .path(binaryName + "/" + version + "/" + binaryName + "-" + version + ".zip") .build().toURL(); - return new URL[]{oldUrl, newUrl}; + return new URL[]{gitUrl, mavenUrl}; } } diff --git a/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java b/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java index 3d15f1d..fa7e21b 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java @@ -15,8 +15,8 @@ public class AllureExecutableProvider { private static final Logger LOGGER = LoggerFactory.getLogger(AllureExecutableProvider.class); - static final String DEFAULT_VERSION = "2.17.2"; - static final String DEFAULT_PATH = "/tmp/allure/2.17.2"; + static final String DEFAULT_VERSION = "2.19.0"; + static final String DEFAULT_PATH = "/tmp/allure/2.19.0"; private static final Pattern EXEC_NAME_PATTERN = compile("[^\\d]*(\\d[0-9\\.]{2,}[a-zA-Z0-9\\-]*)$"); private static final String BINARY_SUBDIR = "binary"; diff --git a/src/main/java/io/qameta/allure/bamboo/AllureGlobalConfig.java b/src/main/java/io/qameta/allure/bamboo/AllureGlobalConfig.java index 1773fd6..41309e3 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureGlobalConfig.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureGlobalConfig.java @@ -1,14 +1,13 @@ package io.qameta.allure.bamboo; +import org.jetbrains.annotations.NotNull; + import javax.annotation.Nullable; import java.io.File; import java.io.Serializable; import java.util.Map; -import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_DOWNLOAD_ENABLED; -import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_DOWNLOAD_URL; -import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_ENABLED_BY_DEFAULT; -import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_LOCAL_STORAGE; +import static io.qameta.allure.bamboo.AllureConstants.*; import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; import static java.lang.Boolean.parseBoolean; @@ -18,29 +17,35 @@ class AllureGlobalConfig implements Serializable { private static final String DEFAULT_DOWNLOAD_BASE_URL = "https://github.com/allure-framework/allure2/releases/download/"; + + private static final String DEFAULT_CLI_BASE_URL = "https://repo.maven.apache.org/maven2/io/qameta/allure/"; public static final String DEFAULT_LOCAL_STORAGE_PATH = new File(getJavaIoTmpDir(), "allure-reports").getPath(); private final boolean downloadEnabled; private final boolean enabledByDefault; private final String localStoragePath; private final String downloadBaseUrl; + private final String downloadCliBaseUrl; AllureGlobalConfig() { - this(TRUE.toString(), FALSE.toString(), DEFAULT_DOWNLOAD_BASE_URL, DEFAULT_LOCAL_STORAGE_PATH); + this(TRUE.toString(), FALSE.toString(), DEFAULT_DOWNLOAD_BASE_URL, DEFAULT_LOCAL_STORAGE_PATH, DEFAULT_CLI_BASE_URL); } - AllureGlobalConfig(String downloadEnabled, String enabledByDefault, String downloadBaseUrl, String localStoragePath) { + AllureGlobalConfig(String downloadEnabled, String enabledByDefault, String downloadBaseUrl, String localStoragePath, String cmdLineUrl) { this.downloadEnabled = isEmpty(downloadEnabled) ? TRUE : parseBoolean(downloadEnabled); this.enabledByDefault = isEmpty(enabledByDefault) ? FALSE : parseBoolean(enabledByDefault); this.downloadBaseUrl = isEmpty(downloadBaseUrl) ? DEFAULT_DOWNLOAD_BASE_URL : downloadBaseUrl; + this.downloadCliBaseUrl = isEmpty(cmdLineUrl) ? DEFAULT_CLI_BASE_URL: cmdLineUrl; this.localStoragePath = isEmpty(localStoragePath) ? DEFAULT_LOCAL_STORAGE_PATH : localStoragePath; } + @NotNull static AllureGlobalConfig fromContext(Map context) { return new AllureGlobalConfig( getSingleValue(context, ALLURE_CONFIG_DOWNLOAD_ENABLED, TRUE.toString()), getSingleValue(context, ALLURE_CONFIG_ENABLED_BY_DEFAULT, FALSE.toString()), getSingleValue(context, ALLURE_CONFIG_DOWNLOAD_URL, null), + getSingleValue(context, ALLURE_CONFIG_DOWNLOAD_CLI_URL, null), getSingleValue(context, ALLURE_CONFIG_LOCAL_STORAGE, null) ); } @@ -71,6 +76,10 @@ String getDownloadBaseUrl() { return downloadBaseUrl; } + String getDownloadCliBaseUrl(){ + return downloadCliBaseUrl; + } + public String getLocalStoragePath() { return localStoragePath; } diff --git a/src/main/java/io/qameta/allure/bamboo/AllureReportServlet.java b/src/main/java/io/qameta/allure/bamboo/AllureReportServlet.java index 3d987a4..4ea6a14 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureReportServlet.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureReportServlet.java @@ -14,7 +14,6 @@ import static org.sonatype.aether.util.StringUtils.isEmpty; import javax.inject.Inject; -import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -30,7 +29,7 @@ import java.util.regex.Pattern; public class AllureReportServlet extends HttpServlet { - private static final Pattern URL_PATTERN = Pattern.compile(".*/plugins/servlet/allure/report/([^/]{2,})/([^/]+)/?(.*)"); + private static final Pattern URL_PATTERN = Pattern.compile(".*/plugins/servlet/allure/report/([^/]{2,})/([^/]+)/?(.*)/"); private static final Logger LOGGER = LoggerFactory.getLogger(AllureReportServlet.class); private final AllureArtifactsManager artifactsManager; private final ResultsSummaryManager resultsSummaryManager; @@ -47,7 +46,7 @@ public static Pattern getUrlPattern() { } @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + protected void doGet(HttpServletRequest request, HttpServletResponse response) { getArtifactUrl(request, response).ifPresent(file -> { try (InputStream inputStream = new URL(file).openStream()) { setResponseHeaders(response, file); @@ -59,7 +58,7 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t } @Override - protected void doHead(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + protected void doHead(HttpServletRequest request, HttpServletResponse response) { getArtifactUrl(request, response).ifPresent(file -> { try (InputStream inputStream = new URL(file).openStream()) { setResponseHeaders(response, file); diff --git a/src/main/java/io/qameta/allure/bamboo/AllureReportTask.java b/src/main/java/io/qameta/allure/bamboo/AllureReportTask.java index 46022d0..38058e0 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureReportTask.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureReportTask.java @@ -20,8 +20,7 @@ public AllureReportTask() { @Override public TaskResult execute(@NotNull TaskContext taskContext) { final BuildLogger buildLogger = taskContext.getBuildLogger(); - buildLogger.addBuildLogHeader("Allure Report", true); - buildLogger.addBuildLogEntry("This allure report task is now a sham. It does nothing, so please use" + + buildLogger.addBuildLogEntry("Allure Report Task: This allure report task is now a sham. It does nothing, so please use" + " the suggested way of configuration as listed in the Allure docs! "); return TaskResultBuilder.newBuilder(taskContext).success().build(); } diff --git a/src/main/java/io/qameta/allure/bamboo/AllureSettingsManager.java b/src/main/java/io/qameta/allure/bamboo/AllureSettingsManager.java index 6ef125c..c242e47 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureSettingsManager.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureSettingsManager.java @@ -3,10 +3,7 @@ import com.atlassian.sal.api.pluginsettings.PluginSettings; import com.atlassian.sal.api.pluginsettings.PluginSettingsFactory; -import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_DOWNLOAD_URL; -import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_DOWNLOAD_ENABLED; -import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_ENABLED_BY_DEFAULT; -import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_LOCAL_STORAGE; +import static io.qameta.allure.bamboo.AllureConstants.*; public class AllureSettingsManager { private final PluginSettings settings; @@ -19,8 +16,9 @@ AllureGlobalConfig getSettings() { final String downloadEnabled = (String) settings.get(ALLURE_CONFIG_DOWNLOAD_ENABLED); final String enableByDefault = (String) settings.get(ALLURE_CONFIG_ENABLED_BY_DEFAULT); final String downloadBaseUrl = (String) settings.get(ALLURE_CONFIG_DOWNLOAD_URL); + final String downloadCliBaseUrl = (String) settings.get(ALLURE_CONFIG_DOWNLOAD_CLI_URL); final String localStorage = (String) settings.get(ALLURE_CONFIG_LOCAL_STORAGE); - return new AllureGlobalConfig( downloadEnabled, enableByDefault, downloadBaseUrl, localStorage); + return new AllureGlobalConfig( downloadEnabled, enableByDefault, downloadBaseUrl, localStorage, downloadCliBaseUrl); } void saveSettings(AllureGlobalConfig config) { diff --git a/src/main/java/io/qameta/allure/bamboo/BambooExecutablesManager.java b/src/main/java/io/qameta/allure/bamboo/BambooExecutablesManager.java index 1c851b1..ef1c256 100644 --- a/src/main/java/io/qameta/allure/bamboo/BambooExecutablesManager.java +++ b/src/main/java/io/qameta/allure/bamboo/BambooExecutablesManager.java @@ -11,6 +11,7 @@ import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.Optional; import static com.atlassian.bamboo.v2.build.agent.capability.CapabilitySetManagerUtils.getSharedCapabilitySet; @@ -76,6 +77,6 @@ private Collection getCapabilityKeys() { } private Optional getCapability(String capabilityKey) { - return ofNullable(capabilitySetManager.getSharedLocalCapabilitySet().getCapability(capabilityKey)); + return ofNullable(Objects.requireNonNull(capabilitySetManager.getSharedLocalCapabilitySet()).getCapability(capabilityKey)); } } diff --git a/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java b/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java new file mode 100644 index 0000000..0439f56 --- /dev/null +++ b/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java @@ -0,0 +1,45 @@ +package io.qameta.allure.bamboo.util; + +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.ArchiveException; +import org.apache.commons.compress.archivers.ArchiveInputStream; +import org.apache.commons.compress.archivers.ArchiveStreamFactory; +import org.apache.commons.compress.utils.IOUtils; +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class ZipUtil { + + public static void unzip(@NotNull Path zipFilePath, String outputDir) throws IOException, ArchiveException { + + final ArchiveStreamFactory asf = new ArchiveStreamFactory(); + + InputStream zipStream = Files.newInputStream(zipFilePath); + ArchiveInputStream ais = asf.createArchiveInputStream(ArchiveStreamFactory.ZIP, zipStream); + + for (ArchiveEntry entry; (entry = ais.getNextEntry()) != null; ) { + Path entryPath = Paths.get(outputDir, entry.getName()); + File entryFile = entryPath.toFile(); + + if (!entry.isDirectory()) { + File parentEntryFile = entryFile.getParentFile(); + if (parentEntryFile.isDirectory() && !(parentEntryFile.mkdirs() || parentEntryFile.exists())) { + throw new IOException("The directory: " + parentEntryFile.getPath() + " couldn't be created successfully"); + } + + try (OutputStream outputStream = Files.newOutputStream(entryPath)) { + IOUtils.copy(ais, outputStream); + } + } else if (!(entryFile.mkdirs() || entryFile.exists())) { + throw new IOException("The directory: " + entryFile.getPath() + " couldn't be created successfully"); + } + } + } +} diff --git a/src/main/resources/allure-bamboo.properties b/src/main/resources/allure-bamboo.properties index 1b48585..c7a29f9 100644 --- a/src/main/resources/allure-bamboo.properties +++ b/src/main/resources/allure-bamboo.properties @@ -23,7 +23,7 @@ allure.task.help.title = Go to Allure website! error.property.empty = The property value should not be empty error.path.absolute = The path should be relative -error.address.placeholder = The pattern should contains exactly one placeholder <%s> +error.address.placeholder = The pattern should contain exactly one placeholder <%s> webitems.system.admin.build.allureReport=Allure Report admin.allureReportConfig.edit.title=Configure Allure Reporting diff --git a/src/test/java/io/qameta/allure/bamboo/AllureCommandLineSupportTest.java b/src/test/java/io/qameta/allure/bamboo/AllureCommandLineSupportTest.java index 8a90b49..f9128d5 100644 --- a/src/test/java/io/qameta/allure/bamboo/AllureCommandLineSupportTest.java +++ b/src/test/java/io/qameta/allure/bamboo/AllureCommandLineSupportTest.java @@ -2,12 +2,13 @@ import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; + public class AllureCommandLineSupportTest { - private AllureCommandLineSupport support = new AllureCommandLineSupport(); + private final AllureCommandLineSupport support = new AllureCommandLineSupport(); @Test public void itShouldReturnNotContainingTestcasesResult() throws Exception { diff --git a/src/test/java/io/qameta/allure/bamboo/AllureDownloaderTest.java b/src/test/java/io/qameta/allure/bamboo/AllureDownloaderTest.java index c2e1a17..c8a76ec 100644 --- a/src/test/java/io/qameta/allure/bamboo/AllureDownloaderTest.java +++ b/src/test/java/io/qameta/allure/bamboo/AllureDownloaderTest.java @@ -8,11 +8,14 @@ import org.mockito.Mock; import org.mockito.junit.MockitoRule; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Paths; import static org.apache.commons.io.FileUtils.deleteQuietly; -import static org.apache.commons.io.FileUtils.getTempDirectoryPath; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.Mockito.when; import static org.mockito.junit.MockitoJUnit.rule; @@ -29,7 +32,7 @@ public class AllureDownloaderTest { @Before public void setUp() { - homeDir = Paths.get(getTempDirectoryPath(), "allure-home").toString(); + homeDir = Paths.get(System.getProperty("java.io.tmpdir"), "allure-home").toString(); settings = new AllureGlobalConfig(); when(settingsManager.getSettings()).thenReturn(settings); } @@ -37,7 +40,8 @@ public void setUp() { @Test public void itShouldDownloadAndExtractAllureRelease() { downloader.downloadAndExtractAllureTo(homeDir, "2.17.2"); - assertTrue(Paths.get(homeDir, "bin", "allure").toFile().exists()); + File f = Paths.get(homeDir, "bin", "allure").toFile(); + assertTrue(f.exists()); } @After diff --git a/src/test/java/io/qameta/allure/bamboo/AllureExecutableProviderTest.java b/src/test/java/io/qameta/allure/bamboo/AllureExecutableProviderTest.java index a05fca8..87891fe 100644 --- a/src/test/java/io/qameta/allure/bamboo/AllureExecutableProviderTest.java +++ b/src/test/java/io/qameta/allure/bamboo/AllureExecutableProviderTest.java @@ -14,13 +14,12 @@ import static io.qameta.allure.bamboo.AllureExecutableProvider.DEFAULT_VERSION; import static io.qameta.allure.bamboo.AllureExecutableProvider.getAllureSubDir; import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.anyString; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.junit.MockitoJUnit.rule; -@SuppressWarnings("OptionalGetWithoutIsPresent") public class AllureExecutableProviderTest { private final String homeDir = "/home/allure"; diff --git a/src/test/java/io/qameta/allure/bamboo/AllureExecutableTest.java b/src/test/java/io/qameta/allure/bamboo/AllureExecutableTest.java index 263749b..df0b684 100644 --- a/src/test/java/io/qameta/allure/bamboo/AllureExecutableTest.java +++ b/src/test/java/io/qameta/allure/bamboo/AllureExecutableTest.java @@ -11,7 +11,7 @@ import static com.google.common.io.Files.createTempDir; import static java.util.Collections.singleton; -import static org.mockito.Matchers.anyString; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.junit.MockitoJUnit.rule; @@ -20,7 +20,7 @@ public class AllureExecutableTest { @Rule public MockitoRule mockitoRule = rule(); - private Path path = Paths.get("/tmp/where-allure/installed"); + private final Path path = Paths.get("/tmp/where-allure/installed"); @Mock private AllureCommandLineSupport cmdLine; @@ -30,6 +30,7 @@ public class AllureExecutableTest { private Path toDir; @Before + @SuppressWarnings("UnstableApiUsage") public void setUp() throws Exception { executable = new AllureExecutable(path, cmdLine); fromDir = createTempDir().toPath(); diff --git a/src/test/java/io/qameta/allure/bamboo/util/ExceptionUtilTest.java b/src/test/java/io/qameta/allure/bamboo/util/ExceptionUtilTest.java index 903101b..ff81e25 100644 --- a/src/test/java/io/qameta/allure/bamboo/util/ExceptionUtilTest.java +++ b/src/test/java/io/qameta/allure/bamboo/util/ExceptionUtilTest.java @@ -3,13 +3,13 @@ import org.junit.Test; import static io.qameta.allure.bamboo.util.ExceptionUtil.stackTraceToString; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertThat; public class ExceptionUtilTest { @Test - public void itShouldPrintStackTraceIntoString() throws Exception { + public void itShouldPrintStackTraceIntoString() { try { throw new RuntimeException("Print me please"); } catch (RuntimeException e) { From b587c28017e129755a6f1647561661ff41647214 Mon Sep 17 00:00:00 2001 From: Manuel Lara Date: Fri, 19 Aug 2022 16:36:23 -0300 Subject: [PATCH 02/15] > AllureArtifactsManager: Ensure the path URL, avoiding having two backslashes together when filePath is concatenated > AllureBuildCompleteAction: Fixing Report URL in the executor.json file. > AllureCommandLineSupport: Increasing timeout to 5 minutes > AllureReportServlet: Rollback URL Pattern Signed-off-by: Manuel Lara --- .../java/io/qameta/allure/bamboo/AllureArtifactsManager.java | 5 +++-- .../io/qameta/allure/bamboo/AllureBuildCompleteAction.java | 2 +- .../io/qameta/allure/bamboo/AllureCommandLineSupport.java | 2 +- .../java/io/qameta/allure/bamboo/AllureReportServlet.java | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java b/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java index 4f7ee1d..488c773 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java @@ -300,12 +300,13 @@ private void downloadAllArtifactsTo(@NotNull FileSystemArtifactLinkDataProvider @Nullable private String getArtifactFile(String filePath, ArtifactLinkDataProvider linkProvider) { + String fixedFilePath = filePath.replaceFirst("^/", ""); if (linkProvider instanceof FileSystemArtifactLinkDataProvider) { return requireNonNull(linkProvider.getRootUrl()) .replaceFirst("BASE_URL", getBaseUrl().build().toString()) - .replace("index.html", isEmpty(filePath) ? "index.html" : filePath); + .replace("index.html", isEmpty(fixedFilePath) ? "index.html" : fixedFilePath); } else { - final Iterable datas = linkProvider.listObjects(filePath); + final Iterable datas = linkProvider.listObjects(fixedFilePath); if (size(datas) == 1) { ArtifactFileData data = datas.iterator().next(); if (data instanceof TrampolineArtifactFileData) { diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java index 85bd7f0..c541cee 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java @@ -193,7 +193,7 @@ private void addExecutorInfo(@NotNull List artifactsTempDirs, @NotNull Imm final String rootUrl = getBambooBaseUrl(); final String buildName = chain.getBuildName(); final String buildUrl = String.format("%s/browse/%s-%s", rootUrl, chain.getPlanKey().getKey(), buildNumber); - final String reportUrl = String.format("%s/plugins/servlet/allure/report/%s/%s/", rootUrl, + final String reportUrl = String.format("%s/plugins/servlet/allure/report/%s/%s", rootUrl, chain.getPlanKey().getKey(), buildNumber); final AddExecutorInfo executorInfo = new AddExecutorInfo(rootUrl, Integer.toString(buildNumber), buildName, buildUrl, reportUrl); artifactsTempDirs.forEach(executorInfo::invoke); diff --git a/src/main/java/io/qameta/allure/bamboo/AllureCommandLineSupport.java b/src/main/java/io/qameta/allure/bamboo/AllureCommandLineSupport.java index 11e601c..c07313a 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureCommandLineSupport.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureCommandLineSupport.java @@ -15,7 +15,7 @@ public class AllureCommandLineSupport { private static final Pattern RESULT_TC_COUNT_REGEX = Pattern.compile(".+Found (\\d+) test cases.+", Pattern.DOTALL); - private static final int GENERATE_TIMEOUT_MS = (int) MINUTES.toMillis(5); + private static final int GENERATE_TIMEOUT_MS = (int) MINUTES.toMillis(10); String runCommand(String cmd, String... args) { return new ProcBuilder(cmd) diff --git a/src/main/java/io/qameta/allure/bamboo/AllureReportServlet.java b/src/main/java/io/qameta/allure/bamboo/AllureReportServlet.java index 4ea6a14..f5bfdbc 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureReportServlet.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureReportServlet.java @@ -29,7 +29,7 @@ import java.util.regex.Pattern; public class AllureReportServlet extends HttpServlet { - private static final Pattern URL_PATTERN = Pattern.compile(".*/plugins/servlet/allure/report/([^/]{2,})/([^/]+)/?(.*)/"); + private static final Pattern URL_PATTERN = Pattern.compile(".*/plugins/servlet/allure/report/([^/]{2,})/([^/]+)/?(.*)"); private static final Logger LOGGER = LoggerFactory.getLogger(AllureReportServlet.class); private final AllureArtifactsManager artifactsManager; private final ResultsSummaryManager resultsSummaryManager; From aaf963db14dab9077ab98ac9d7bc663bf3de7966 Mon Sep 17 00:00:00 2001 From: Manuel Lara Date: Fri, 19 Aug 2022 16:37:11 -0300 Subject: [PATCH 03/15] > AllureBuildCompleteAction: Adding more historical info (trends and so on). Signed-off-by: Manuel Lara --- .../io/qameta/allure/bamboo/AllureBuildCompleteAction.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java index c541cee..96008d9 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java @@ -41,8 +41,7 @@ public class AllureBuildCompleteAction extends BaseConfigurablePlugin implements PostChainAction { private static final Logger LOGGER = LoggerFactory.getLogger(AllureBuildCompleteAction.class); - private static final List HISTORY_FILES = asList("history.json", "history-trend.json"); - + private static final List HISTORY_FILES = asList("history.json", "history-trend.json", "categories-trend.json", "duration-trend.json"); private final AllureExecutableProvider allureExecutable; private final AllureSettingsManager settingsManager; private final AllureArtifactsManager artifactsManager; From c6108044c54afcad80149e605e020e88904eda3a Mon Sep 17 00:00:00 2001 From: Manuel Lara Date: Fri, 19 Aug 2022 16:38:48 -0300 Subject: [PATCH 04/15] > Customize the logo of each report from each build from the bamboo UI > Bug: When you try to uncheck an option from Bamboo UI the option is not saved. > Download Util class we created to download logo and allure binary > The deprecated logo was changed due to it being confused. (It is not deprecated, it is just not necessary) > The task description was changed > Bug: If you add an allure task to your plan the build fails due to API incompatibility Signed-off-by: Manuel Lara --- pom.xml | 10 +++++ .../bamboo/AllureBuildCompleteAction.java | 7 +++- .../allure/bamboo/AllureBuildConfig.java | 40 +++++++++++++----- .../bamboo/AllureBuildConfigurator.java | 3 +- .../qameta/allure/bamboo/AllureConstants.java | 4 ++ .../allure/bamboo/AllureDownloader.java | 19 +-------- .../allure/bamboo/AllureExecutable.java | 42 +++++++++++++++++++ .../bamboo/AllureExecutableProvider.java | 1 + .../allure/bamboo/AllureGlobalConfig.java | 36 +++++++++------- .../allure/bamboo/AllureSettingsManager.java | 7 +++- .../allure/bamboo/info/AllurePlugins.java | 35 ++++++++++++++++ .../qameta/allure/bamboo/util/Downloader.java | 34 +++++++++++++++ src/main/resources/allure-bamboo.properties | 5 ++- src/main/resources/atlassian-plugin.xml | 6 +-- .../editAllureBambooConfiguration.ftl | 2 + .../templates/editAllureReportConfig.ftl | 2 + 16 files changed, 202 insertions(+), 51 deletions(-) create mode 100644 src/main/java/io/qameta/allure/bamboo/info/AllurePlugins.java create mode 100644 src/main/java/io/qameta/allure/bamboo/util/Downloader.java diff --git a/pom.xml b/pom.xml index 895062c..4d3e076 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,16 @@ + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + 2.13.3 + + + com.fasterxml.jackson.core + jackson-databind + 2.13.3 + org.buildobjects jproc diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java index 96008d9..ef6f4fc 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java @@ -9,7 +9,6 @@ import com.atlassian.bamboo.resultsummary.ResultsSummary; import com.atlassian.bamboo.resultsummary.ResultsSummaryManager; import com.atlassian.bamboo.v2.build.BaseConfigurablePlugin; -import com.atlassian.bonnie.search.summary.Summary; import com.atlassian.spring.container.ContainerManager; import io.qameta.allure.bamboo.info.AddExecutorInfo; import org.apache.commons.lang3.StringUtils; @@ -98,6 +97,12 @@ public void execute(@NotNull ImmutableChain chain, @NotNull ChainResultsSummary } else { LOGGER.info("Starting allure generate into {} for {}", allureReportDir.getPath(), chain.getName()); prepareResults(artifactsPaths.stream().map(Path::toFile).collect(toList()), chain, chainExecution); + + // Setting the new logo in the allure libraries before generate the report. + if (globalConfig.isCustomLogoEnabled()) { + allure.setCustomLogo(buildConfig.getCustomLogoUrl()); + } + allure.generate(artifactsPaths, allureReportDir.toPath()); LOGGER.info("Allure has been generated successfully for {}", chain.getName()); artifactsManager.uploadReportArtifacts(chain, chainResultsSummary, allureReportDir) diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java index 7395c4c..f0917d7 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java @@ -1,14 +1,15 @@ package io.qameta.allure.bamboo; +import org.apache.commons.validator.routines.UrlValidator; + +import javax.annotation.Nullable; import java.io.Serializable; import java.util.Map; -import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_ARTIFACT_NAME; -import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_ENABLED; -import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_EXECUTABLE; -import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_FAILED_ONLY; +import static io.qameta.allure.bamboo.AllureConstants.*; import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; +import static java.util.Optional.ofNullable; import static org.apache.commons.lang.StringUtils.isEmpty; public class AllureBuildConfig implements Serializable { @@ -16,22 +17,34 @@ public class AllureBuildConfig implements Serializable { private final String executable; private final boolean enabled; private final String artifactName; + private final String logoUrl; + private final static String DEFAULT_ARTIFACT_NAME = "allure-results"; + public final static String DEFAULT_CUSTOM_LOGO_URL = "https://qameta.io/allure-report/img/reportlogo.svg"; - private AllureBuildConfig(String executable, String enabled, String onlyForFailed, String artifactName) { + private AllureBuildConfig(String executable, String enabled, String onlyForFailed, String artifactName, String logoUrl) { this.onlyForFailed = isEmpty(onlyForFailed) ? TRUE : Boolean.parseBoolean(onlyForFailed); this.enabled = isEmpty(enabled) ? FALSE : Boolean.parseBoolean(enabled); this.executable = executable; this.artifactName = artifactName; + // If the URL is not a valid URL it will be omitted + UrlValidator urlValidator = new UrlValidator(); + this.logoUrl = urlValidator.isValid(logoUrl) ? logoUrl : AllureBuildConfig.DEFAULT_CUSTOM_LOGO_URL; } static AllureBuildConfig fromContext(Map context) { - final String failedOnlyString = context.get(ALLURE_CONFIG_FAILED_ONLY); - final String enableAllureString = context.get(ALLURE_CONFIG_ENABLED); return new AllureBuildConfig( - context.get(ALLURE_CONFIG_EXECUTABLE), - enableAllureString, - failedOnlyString, - context.get(ALLURE_CONFIG_ARTIFACT_NAME)); + getSingleValue(context, ALLURE_CONFIG_EXECUTABLE, null), + getSingleValue(context, ALLURE_CONFIG_ENABLED, FALSE.toString()), + getSingleValue(context, ALLURE_CONFIG_FAILED_ONLY, FALSE.toString()), + getSingleValue(context, ALLURE_CONFIG_ARTIFACT_NAME, AllureBuildConfig.DEFAULT_ARTIFACT_NAME), + getSingleValue(context, ALLURE_CUSTOM_LOGO_PATH, AllureBuildConfig.DEFAULT_CUSTOM_LOGO_URL)); + } + + @Nullable + private static String getSingleValue(Map context, String key, String defaultVal) { + return ofNullable(context.get(key)) + .map(value -> value instanceof String[] ? ((String[]) value)[0] : (String) value) + .orElse(defaultVal); } boolean isOnlyForFailed() { @@ -53,4 +66,9 @@ boolean isEnabled() { public String getArtifactName() { return artifactName; } + + public String getCustomLogoUrl() { + return this.logoUrl; + } + } diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildConfigurator.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildConfigurator.java index f4d1e14..ed798d3 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildConfigurator.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildConfigurator.java @@ -10,7 +10,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import static com.atlassian.bamboo.plan.PlanClassHelper.isChain; +import static com.atlassian.bamboo.plan.PlanClassHelper.isChain; import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_ENABLED; import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_EXECUTABLE; import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_FAILED_ONLY; @@ -18,7 +18,6 @@ import static java.util.Optional.ofNullable; import static org.apache.commons.lang.StringUtils.isEmpty; -@SuppressWarnings("unchecked") public class AllureBuildConfigurator extends BaseConfigurablePlugin implements MiscellaneousPlanConfigurationPlugin { diff --git a/src/main/java/io/qameta/allure/bamboo/AllureConstants.java b/src/main/java/io/qameta/allure/bamboo/AllureConstants.java index 4cae816..331e5df 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureConstants.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureConstants.java @@ -39,6 +39,10 @@ final class AllureConstants { static String ALLURE_CONFIG_DOWNLOAD_CLI_URL = "custom.allure.config.download.cli.url"; static String ALLURE_CONFIG_LOCAL_STORAGE = "custom.allure.config.local.storage"; + // ALLURE CUSTOM LOGO + static String ALLURE_CUSTOM_LOGO_ENABLED = "custom.allure.config.logo.enabled"; + static String ALLURE_CUSTOM_LOGO_PATH = "custom.allure.logo.url"; + private AllureConstants() { } } diff --git a/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java b/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java index 887a34d..ef4eff7 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java @@ -1,29 +1,24 @@ package io.qameta.allure.bamboo; +import io.qameta.allure.bamboo.util.Downloader; import io.qameta.allure.bamboo.util.ZipUtil; import org.apache.commons.compress.archivers.ArchiveException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; -import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; -import java.net.URLConnection; import java.nio.file.*; import java.util.Optional; -import static java.lang.Integer.getInteger; import static java.nio.file.Files.createTempFile; -import static java.util.concurrent.TimeUnit.SECONDS; import static javax.ws.rs.core.UriBuilder.fromPath; import static org.apache.commons.io.FileUtils.deleteQuietly; import static org.apache.commons.io.FileUtils.moveDirectory; class AllureDownloader { private static final Logger LOGGER = LoggerFactory.getLogger(AllureDownloader.class); - private static final int CONN_TIMEOUT_MS = (int) SECONDS.toMillis(getInteger("allure.download.conn.timeout.sec", 10)); - private static final int DOWNLOAD_TIMEOUT_MS = (int) SECONDS.toMillis(getInteger("allure.download.timeout.sec", 60)); private final AllureSettingsManager settingsManager; @@ -62,17 +57,7 @@ private Optional downloadAllure(String version) { try { final Path downloadToFile = createTempFile("allure", ".zip"); LOGGER.info("Downloading allure.zip from {} to {}", url, downloadToFile); - final URLConnection connection = url.openConnection(); - connection.setConnectTimeout(CONN_TIMEOUT_MS); - connection.setReadTimeout(DOWNLOAD_TIMEOUT_MS); - connection.setRequestProperty("Connection", "close"); - connection.setRequestProperty("Pragma", "no-cache"); - ((HttpURLConnection) connection).setInstanceFollowRedirects(true); - connection.connect(); - try (InputStream input = connection.getInputStream()) { - Files.copy(input, downloadToFile, StandardCopyOption.REPLACE_EXISTING); - return Optional.of(downloadToFile); - } + return Downloader.download(url, downloadToFile); } catch (Exception e) { LOGGER .warn("Failed to download from {}. Root cause : {}.", diff --git a/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java b/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java index a052e31..a9eb406 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java @@ -1,15 +1,23 @@ package io.qameta.allure.bamboo; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; +import io.qameta.allure.bamboo.info.AllurePlugins; +import io.qameta.allure.bamboo.util.Downloader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; +import java.io.File; +import java.io.IOException; +import java.net.URL; import java.nio.file.Path; import java.util.Collection; import java.util.LinkedList; import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; +import static javax.ws.rs.core.UriBuilder.fromPath; class AllureExecutable { private static final Logger LOGGER = LoggerFactory.getLogger(AllureExecutable.class); @@ -41,6 +49,40 @@ AllureGenerateResult generate(Collection sourceDirs, Path targetDir) { } } + + @SuppressWarnings("ResultOfMethodCallIgnored") + public void setCustomLogo(String logoUrl) { + final String pluginName = "custom-logo-plugin"; + final String allureConfigFileName = "allure.yml"; + final String logoOriginalName = "custom-logo.svg"; + final String logoBackupName = logoOriginalName + "bkp"; + + Path rootPath = this.cmdPath.getParent().getParent(); + Path configFolder = rootPath.resolve("config"); + Path logoPluginFolder = rootPath.resolve("plugins").resolve(pluginName).resolve("static"); + + /// Editing Yaml to add plugin + ObjectMapper objectMapper = new YAMLMapper(); + try { + File configFile = configFolder.resolve(allureConfigFileName).toFile(); + AllurePlugins ap = objectMapper.readValue(configFile, AllurePlugins.class); + //Saving the file only if it necessary + if (ap.registerPlugin(pluginName)) { + objectMapper.writeValue(configFile, ap); + } + /// Backup the original one + URL srcLogoUrl = fromPath(logoUrl).build().toURL(); + File bkp = logoPluginFolder.resolve(logoBackupName).toFile(); + logoPluginFolder.resolve(logoOriginalName).toFile().renameTo(bkp); + /// Replace with the new one + Downloader.download(srcLogoUrl, logoPluginFolder.resolve(logoOriginalName)); + + } catch (IOException e) { + LOGGER.error(e.toString()); + throw new RuntimeException(e); + } + } + Path getCmdPath() { return cmdPath; } diff --git a/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java b/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java index fa7e21b..5cc8b66 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java @@ -4,6 +4,7 @@ import static java.util.Objects.requireNonNull; import static java.util.regex.Pattern.compile; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/io/qameta/allure/bamboo/AllureGlobalConfig.java b/src/main/java/io/qameta/allure/bamboo/AllureGlobalConfig.java index 41309e3..1256701 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureGlobalConfig.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureGlobalConfig.java @@ -17,36 +17,38 @@ class AllureGlobalConfig implements Serializable { private static final String DEFAULT_DOWNLOAD_BASE_URL = "https://github.com/allure-framework/allure2/releases/download/"; - private static final String DEFAULT_CLI_BASE_URL = "https://repo.maven.apache.org/maven2/io/qameta/allure/"; public static final String DEFAULT_LOCAL_STORAGE_PATH = new File(getJavaIoTmpDir(), "allure-reports").getPath(); private final boolean downloadEnabled; + private final boolean customLogoEnabled; private final boolean enabledByDefault; private final String localStoragePath; private final String downloadBaseUrl; private final String downloadCliBaseUrl; AllureGlobalConfig() { - this(TRUE.toString(), FALSE.toString(), DEFAULT_DOWNLOAD_BASE_URL, DEFAULT_LOCAL_STORAGE_PATH, DEFAULT_CLI_BASE_URL); + this(TRUE.toString(), FALSE.toString(), DEFAULT_DOWNLOAD_BASE_URL, DEFAULT_LOCAL_STORAGE_PATH, DEFAULT_CLI_BASE_URL, TRUE.toString()); } - AllureGlobalConfig(String downloadEnabled, String enabledByDefault, String downloadBaseUrl, String localStoragePath, String cmdLineUrl) { + AllureGlobalConfig(String downloadEnabled, String enabledByDefault, String downloadBaseUrl, String localStoragePath, String cmdLineUrl, String customLogoEnable) { this.downloadEnabled = isEmpty(downloadEnabled) ? TRUE : parseBoolean(downloadEnabled); this.enabledByDefault = isEmpty(enabledByDefault) ? FALSE : parseBoolean(enabledByDefault); this.downloadBaseUrl = isEmpty(downloadBaseUrl) ? DEFAULT_DOWNLOAD_BASE_URL : downloadBaseUrl; - this.downloadCliBaseUrl = isEmpty(cmdLineUrl) ? DEFAULT_CLI_BASE_URL: cmdLineUrl; + this.downloadCliBaseUrl = isEmpty(cmdLineUrl) ? DEFAULT_CLI_BASE_URL : cmdLineUrl; this.localStoragePath = isEmpty(localStoragePath) ? DEFAULT_LOCAL_STORAGE_PATH : localStoragePath; + this.customLogoEnabled = isEmpty(customLogoEnable) ? TRUE : parseBoolean(customLogoEnable); } @NotNull static AllureGlobalConfig fromContext(Map context) { return new AllureGlobalConfig( - getSingleValue(context, ALLURE_CONFIG_DOWNLOAD_ENABLED, TRUE.toString()), + getSingleValue(context, ALLURE_CONFIG_DOWNLOAD_ENABLED, FALSE.toString()), getSingleValue(context, ALLURE_CONFIG_ENABLED_BY_DEFAULT, FALSE.toString()), - getSingleValue(context, ALLURE_CONFIG_DOWNLOAD_URL, null), - getSingleValue(context, ALLURE_CONFIG_DOWNLOAD_CLI_URL, null), - getSingleValue(context, ALLURE_CONFIG_LOCAL_STORAGE, null) + getSingleValue(context, ALLURE_CONFIG_DOWNLOAD_URL, DEFAULT_DOWNLOAD_BASE_URL), + getSingleValue(context, ALLURE_CONFIG_LOCAL_STORAGE, DEFAULT_LOCAL_STORAGE_PATH), + getSingleValue(context, ALLURE_CONFIG_DOWNLOAD_CLI_URL, DEFAULT_CLI_BASE_URL), + getSingleValue(context, ALLURE_CUSTOM_LOGO_ENABLED, FALSE.toString()) ); } @@ -57,6 +59,15 @@ private static String getSingleValue(Map context, String key, String defaultVal) .orElse(defaultVal); } + void toContext(@NotNull Map context) { + context.put(ALLURE_CONFIG_DOWNLOAD_ENABLED, isDownloadEnabled()); + context.put(ALLURE_CONFIG_ENABLED_BY_DEFAULT, isEnabledByDefault()); + context.put(ALLURE_CONFIG_DOWNLOAD_URL, getDownloadBaseUrl()); + context.put(ALLURE_CONFIG_DOWNLOAD_CLI_URL, getDownloadCliBaseUrl()); + context.put(ALLURE_CONFIG_LOCAL_STORAGE, getLocalStoragePath()); + context.put(ALLURE_CUSTOM_LOGO_ENABLED, isCustomLogoEnabled()); + } + boolean isDownloadEnabled() { return downloadEnabled; } @@ -65,18 +76,15 @@ boolean isEnabledByDefault() { return enabledByDefault; } - void toContext(Map context) { - context.put(ALLURE_CONFIG_DOWNLOAD_ENABLED, isDownloadEnabled()); - context.put(ALLURE_CONFIG_ENABLED_BY_DEFAULT, isEnabledByDefault()); - context.put(ALLURE_CONFIG_DOWNLOAD_URL, getDownloadBaseUrl()); - context.put(ALLURE_CONFIG_LOCAL_STORAGE, getLocalStoragePath()); + boolean isCustomLogoEnabled() { + return customLogoEnabled; } String getDownloadBaseUrl() { return downloadBaseUrl; } - String getDownloadCliBaseUrl(){ + String getDownloadCliBaseUrl() { return downloadCliBaseUrl; } diff --git a/src/main/java/io/qameta/allure/bamboo/AllureSettingsManager.java b/src/main/java/io/qameta/allure/bamboo/AllureSettingsManager.java index c242e47..7ed0bab 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureSettingsManager.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureSettingsManager.java @@ -14,17 +14,20 @@ public AllureSettingsManager(PluginSettingsFactory settingsFactory) { AllureGlobalConfig getSettings() { final String downloadEnabled = (String) settings.get(ALLURE_CONFIG_DOWNLOAD_ENABLED); + final String customLogoEnabled = (String) settings.get(ALLURE_CUSTOM_LOGO_ENABLED); final String enableByDefault = (String) settings.get(ALLURE_CONFIG_ENABLED_BY_DEFAULT); final String downloadBaseUrl = (String) settings.get(ALLURE_CONFIG_DOWNLOAD_URL); final String downloadCliBaseUrl = (String) settings.get(ALLURE_CONFIG_DOWNLOAD_CLI_URL); final String localStorage = (String) settings.get(ALLURE_CONFIG_LOCAL_STORAGE); - return new AllureGlobalConfig( downloadEnabled, enableByDefault, downloadBaseUrl, localStorage, downloadCliBaseUrl); + return new AllureGlobalConfig( downloadEnabled, enableByDefault, downloadBaseUrl, localStorage, downloadCliBaseUrl, customLogoEnabled); } void saveSettings(AllureGlobalConfig config) { settings.put(ALLURE_CONFIG_DOWNLOAD_ENABLED, String.valueOf(config.isDownloadEnabled())); - settings.put(ALLURE_CONFIG_ENABLED_BY_DEFAULT, String.valueOf(config.isEnabledByDefault())); + settings.put(ALLURE_CUSTOM_LOGO_ENABLED, String.valueOf(config.isCustomLogoEnabled())); settings.put(ALLURE_CONFIG_DOWNLOAD_URL, String.valueOf(config.getDownloadBaseUrl())); settings.put(ALLURE_CONFIG_LOCAL_STORAGE, String.valueOf(config.getLocalStoragePath())); + settings.put(ALLURE_CONFIG_ENABLED_BY_DEFAULT, String.valueOf(config.isEnabledByDefault())); + } } diff --git a/src/main/java/io/qameta/allure/bamboo/info/AllurePlugins.java b/src/main/java/io/qameta/allure/bamboo/info/AllurePlugins.java new file mode 100644 index 0000000..2bd7d56 --- /dev/null +++ b/src/main/java/io/qameta/allure/bamboo/info/AllurePlugins.java @@ -0,0 +1,35 @@ +package io.qameta.allure.bamboo.info; + +import java.util.List; + +public class AllurePlugins { + private List plugins; + + public AllurePlugins(List plugins) { + this.plugins = plugins; + } + + public AllurePlugins() { + } + + public boolean isRegistered(String pluginName) { + return plugins.contains(pluginName); + } + + public List getPlugins() { + return plugins; + } + + public boolean registerPlugin(String pluginName) { + if (!this.isRegistered(pluginName)) { + this.plugins.add(pluginName); + return true; + } + return false; + } + + @Override + public String toString() { + return "\nplugins: " + this.plugins; + } +} diff --git a/src/main/java/io/qameta/allure/bamboo/util/Downloader.java b/src/main/java/io/qameta/allure/bamboo/util/Downloader.java new file mode 100644 index 0000000..371163f --- /dev/null +++ b/src/main/java/io/qameta/allure/bamboo/util/Downloader.java @@ -0,0 +1,34 @@ +package io.qameta.allure.bamboo.util; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.Optional; + +import static java.lang.Integer.getInteger; +import static java.util.concurrent.TimeUnit.SECONDS; + +public class Downloader { + private static final int CONN_TIMEOUT_MS = (int) SECONDS.toMillis(getInteger("allure.download.conn.timeout.sec", 20)); + private static final int DOWNLOAD_TIMEOUT_MS = (int) SECONDS.toMillis(getInteger("allure.download.timeout.sec", 120)); + + public static Optional download(URL url, Path target) throws IOException { + final URLConnection connection = url.openConnection(); + connection.setConnectTimeout(CONN_TIMEOUT_MS); + connection.setReadTimeout(DOWNLOAD_TIMEOUT_MS); + connection.setRequestProperty("Connection", "close"); + connection.setRequestProperty("Pragma", "no-cache"); + ((HttpURLConnection) connection).setInstanceFollowRedirects(true); + connection.connect(); + try (InputStream input = connection.getInputStream()) { + Files.copy(input, target, StandardCopyOption.REPLACE_EXISTING); + return Optional.of(target); + } + } +} diff --git a/src/main/resources/allure-bamboo.properties b/src/main/resources/allure-bamboo.properties index c7a29f9..ef3355b 100644 --- a/src/main/resources/allure-bamboo.properties +++ b/src/main/resources/allure-bamboo.properties @@ -41,4 +41,7 @@ allure.config.download.url.error.required=Allure binary base url is required allure.config.local.storage.label=Allure local storage allure.config.local.storage.label.required=Allure local storage is required build.allure.title=Allure Report -buildResult.allure.title=Allure Report \ No newline at end of file +buildResult.allure.title=Allure Report + +allure.config.logo.enabled.label=Enable report custom logo +custom.allure.logo.url.label=Custom logo URL (svg) \ No newline at end of file diff --git a/src/main/resources/atlassian-plugin.xml b/src/main/resources/atlassian-plugin.xml index ec1a924..94ba08f 100644 --- a/src/main/resources/atlassian-plugin.xml +++ b/src/main/resources/atlassian-plugin.xml @@ -3,7 +3,7 @@ ${project.description} ${project.version} - images/icon.png + images/logo.png images/logo.png 1 true @@ -17,8 +17,8 @@ - WARNING: this is deprecated way of building Allure Report, please refer the official guide to get more info - + This task is automatically executed without adding this task to your pipeline if you enable the allure report generation in the "Other" tab. But you can add it if you want to see it in your pipeline + diff --git a/src/main/resources/templates/editAllureBambooConfiguration.ftl b/src/main/resources/templates/editAllureBambooConfiguration.ftl index 6d094c3..a4bbe48 100644 --- a/src/main/resources/templates/editAllureBambooConfiguration.ftl +++ b/src/main/resources/templates/editAllureBambooConfiguration.ftl @@ -9,4 +9,6 @@ [@ww.textfield labelKey="custom.allure.artifact.name.label" name="custom.allure.artifact.name" required="false"/] + [@ww.textfield labelKey="custom.allure.logo.url.label" name="custom.allure.logo.url" required="false"/] + [/@ui.bambooSection] \ No newline at end of file diff --git a/src/main/resources/templates/editAllureReportConfig.ftl b/src/main/resources/templates/editAllureReportConfig.ftl index 8091c44..f93e505 100644 --- a/src/main/resources/templates/editAllureReportConfig.ftl +++ b/src/main/resources/templates/editAllureReportConfig.ftl @@ -20,6 +20,8 @@ ] [@ww.checkbox labelKey='allure.config.download.enabled.label' name='custom.allure.config.download.enabled' toggle='true' /] + [@ww.checkbox labelKey='allure.config.logo.enabled.label' name='custom.allure.config.logo.enabled' toggle='true' /] + [@ww.checkbox labelKey='allure.config.enabled.default.label' name='custom.allure.config.enabled.default' toggle='true' /] [@ww.textfield labelKey="allure.config.download.url.label" name="custom.allure.config.download.url" required="true"/] From 830b0382d6ef271a172aab63ef4ffddf3583f319 Mon Sep 17 00:00:00 2001 From: Manuel Lara Date: Fri, 19 Aug 2022 16:39:33 -0300 Subject: [PATCH 05/15] > Bug-fixed: If a plan execution fails the history is missing for the next execution. Signed-off-by: Manuel Lara --- .../allure/bamboo/AllureArtifactsManager.java | 2 -- .../allure/bamboo/AllureBuildCompleteAction.java | 16 ++++++++++------ .../io/qameta/allure/bamboo/util/ZipUtil.java | 2 ++ src/main/resources/atlassian-plugin.xml | 5 ++++- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java b/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java index 488c773..0881476 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java @@ -22,7 +22,6 @@ import com.atlassian.bamboo.build.artifact.handlers.ArtifactHandlersService; import com.atlassian.bamboo.chains.ChainResultsSummary; import com.atlassian.bamboo.chains.ChainStageResult; -import com.atlassian.bamboo.plan.PlanKeys; import com.atlassian.bamboo.plan.PlanResultKey; import com.atlassian.bamboo.plan.artifact.ArtifactDefinitionContextImpl; import com.atlassian.bamboo.plan.cache.ImmutableChain; @@ -89,7 +88,6 @@ public class AllureArtifactsManager { private static final Logger LOGGER = LoggerFactory.getLogger(AllureArtifactsManager.class); private static final String REPORTS_SUBDIR = "allure-reports"; - private final PluginAccessor pluginAccessor; private final ArtifactHandlersService artifactHandlersService; private final BuildDefinitionManager buildDefinitionManager; diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java index ef6f4fc..cb4d6a3 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java @@ -10,16 +10,18 @@ import com.atlassian.bamboo.resultsummary.ResultsSummaryManager; import com.atlassian.bamboo.v2.build.BaseConfigurablePlugin; import com.atlassian.spring.container.ContainerManager; +import com.google.gson.JsonParser; import io.qameta.allure.bamboo.info.AddExecutorInfo; +import io.qameta.allure.bamboo.util.Downloader; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; -import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.nio.file.Files; @@ -31,6 +33,7 @@ import static io.qameta.allure.bamboo.AllureBuildResult.allureBuildResult; import static io.qameta.allure.bamboo.util.ExceptionUtil.stackTraceToString; import static java.lang.String.format; +import static java.nio.file.Files.createTempFile; import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; import static org.apache.commons.io.FileUtils.deleteQuietly; @@ -161,13 +164,14 @@ private Optional getLastBuildNumberWithHistory(String planKey, int buil private boolean historyArtifactExists(String planKey, int buildId) { String artifactUrl = getHistoryArtifactUrl("history.json", planKey, buildId); + JsonParser parser = new JsonParser(); try { - HttpURLConnection.setFollowRedirects(false); - HttpURLConnection con = (HttpURLConnection) new URL(artifactUrl).openConnection(); - con.setRequestMethod("HEAD"); - return con.getResponseCode() == HttpURLConnection.HTTP_OK; + final Path historyTmpFile = createTempFile("history", ".json"); + Downloader.download(new URL(artifactUrl), historyTmpFile); + parser.parse(new FileReader(historyTmpFile.toFile())); + return true; } catch (Exception e) { - LOGGER.info("Cannot connect to artifact {}.", artifactUrl, e); + LOGGER.info("Cannot connect to artifact or the artifact is not valid {}.", artifactUrl, e); return false; } } diff --git a/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java b/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java index 0439f56..140faa4 100644 --- a/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java +++ b/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java @@ -42,4 +42,6 @@ public static void unzip(@NotNull Path zipFilePath, String outputDir) throws IOE } } } + + } diff --git a/src/main/resources/atlassian-plugin.xml b/src/main/resources/atlassian-plugin.xml index 94ba08f..be1303c 100644 --- a/src/main/resources/atlassian-plugin.xml +++ b/src/main/resources/atlassian-plugin.xml @@ -17,7 +17,10 @@ - This task is automatically executed without adding this task to your pipeline if you enable the allure report generation in the "Other" tab. But you can add it if you want to see it in your pipeline + + If you enable the allure report generation in the "Other" tab, this task is automatically executed without + adding it to your pipeline. However, you can still add it to your pipeline if you want to see it. + From 71406ec4fd013347c4ea7fafb03f881a08f87989 Mon Sep 17 00:00:00 2001 From: Manuel Lara Date: Fri, 19 Aug 2022 16:40:09 -0300 Subject: [PATCH 06/15] > Plan Titles customization > Allure removed from the title. (it's not customizable) > A link was created to download the report for evidence in other systems. > The logo can have other types not only SVG. > Fix some dependencies conflicts Signed-off-by: Manuel Lara --- pom.xml | 98 ++++++++++ .../bamboo/AllureBuildCompleteAction.java | 55 +++++- .../allure/bamboo/AllureExecutable.java | 30 ++-- .../info/allurewidgets/summary/Statistic.java | 168 ++++++++++++++++++ .../info/allurewidgets/summary/Summary.java | 125 +++++++++++++ .../info/allurewidgets/summary/Time.java | 168 ++++++++++++++++++ .../bamboo/util/FileStringReplacer.java | 25 +++ .../io/qameta/allure/bamboo/util/ZipUtil.java | 16 +- .../resources/templates/viewAllureReport.ftl | 4 +- 9 files changed, 669 insertions(+), 20 deletions(-) create mode 100644 src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Statistic.java create mode 100644 src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Summary.java create mode 100644 src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Time.java create mode 100644 src/main/java/io/qameta/allure/bamboo/util/FileStringReplacer.java diff --git a/pom.xml b/pom.xml index 4d3e076..641e6c2 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ + 4.0.0 @@ -41,6 +42,11 @@ jackson-dataformat-yaml 2.13.3 + + com.google.code.gson + gson + 2.9.0 + com.fasterxml.jackson.core jackson-databind @@ -56,6 +62,64 @@ atlassian-bamboo-web ${bamboo.version} provided + + + com.google.code.gson + gson + + + commons-beanutils + commons-beanutils + + + org.hamcrest + hamcrest-core + + + com.fasterxml.jackson.core + jackson-databind + + + junit + junit + + + log4j + log4j + + + org.slf4j + slf4j-api + + + net.bytebuddy + byte-buddy + + + org.objenesis + objenesis + + + commons-collections + commons-collections + + + commons-lang + commons-lang + + + commons-logging + commons-logging + + + com.fasterxml.jackson.core + jackson-core + + + org.yaml + snakeyaml + + com.atlassian.templaterenderer @@ -109,6 +173,12 @@ junit 4.13.2 test + + + org.hamcrest + hamcrest-core + + org.mockito @@ -128,6 +198,20 @@ atlassian-plugins-osgi-testrunner ${plugin.testrunner.version} test + + + com.google.code.gson + gson + + + commons-beanutils + commons-beanutils + + + commons-io + commons-io + + javax.ws.rs @@ -145,6 +229,20 @@ json-lib 2.4 jdk15 + + + commons-beanutils + commons-beanutils + + + commons-collections + commons-collections + + + commons-logging + commons-logging + + diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java index cb4d6a3..fe74d53 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java @@ -10,24 +10,28 @@ import com.atlassian.bamboo.resultsummary.ResultsSummaryManager; import com.atlassian.bamboo.v2.build.BaseConfigurablePlugin; import com.atlassian.spring.container.ContainerManager; +import com.google.gson.Gson; import com.google.gson.JsonParser; import io.qameta.allure.bamboo.info.AddExecutorInfo; +import io.qameta.allure.bamboo.info.allurewidgets.summary.Summary; import io.qameta.allure.bamboo.util.Downloader; +import io.qameta.allure.bamboo.util.FileStringReplacer; +import io.qameta.allure.bamboo.util.ZipUtil; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.net.URL; import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.*; +import java.util.regex.Pattern; + import static com.google.common.io.Files.createTempDir; import static io.qameta.allure.bamboo.AllureBuildResult.allureBuildResult; @@ -105,12 +109,18 @@ public void execute(@NotNull ImmutableChain chain, @NotNull ChainResultsSummary if (globalConfig.isCustomLogoEnabled()) { allure.setCustomLogo(buildConfig.getCustomLogoUrl()); } - allure.generate(artifactsPaths, allureReportDir.toPath()); + // Setting report name + this.finalize(allureReportDir, chainExecution.getPlanResultKey().getBuildNumber(), chain.getBuildName()); + + // Create an exportable zip with the report + ZipUtil.zipFolder(allureReportDir.toPath(), allureReportDir.toPath().resolve("report.zip")); + LOGGER.info("Allure has been generated successfully for {}", chain.getName()); artifactsManager.uploadReportArtifacts(chain, chainResultsSummary, allureReportDir) .ifPresent(result -> result.dumpToCustomData(customBuildData)); + } } catch (Exception e) { LOGGER.error("Failed to build allure report for {}", chain.getName(), e); @@ -121,6 +131,40 @@ public void execute(@NotNull ImmutableChain chain, @NotNull ChainResultsSummary } } + /** + * I'm a friend, and it's a gift for all you that wants to customize allure report for your projects. :) + * @param allureReportDir + * @param buildNumber + * @param buildName + * @throws IOException + */ + private void finalize(@NotNull File allureReportDir, int buildNumber, String buildName) throws IOException { + //////////////////// + // Update Report Name (It is the way now) + Path widgetsJsonPath = Paths.get(allureReportDir.getAbsolutePath()).resolve("widgets").resolve("summary.json"); + Gson gson = new Gson(); + Summary summary = gson.fromJson(new FileReader(widgetsJsonPath.toFile()), Summary.class); + summary.setReportName("Build #" + buildNumber + " - " + buildName); + Writer json = new FileWriter(widgetsJsonPath.toFile()); + gson.toJson(summary, Summary.class, json); + json.flush(); + json.close(); + //////////////////// + // Deleting title from Logo + Path appJsPath = Paths.get(allureReportDir.getAbsolutePath()).resolve("app.js"); + FileStringReplacer.replaceInFile(appJsPath, + Pattern.compile(">Allure", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + "> " + ); + //////////////////// + // Changing page title + Path indexHtmlPath = Paths.get(allureReportDir.getAbsolutePath()).resolve("index.html"); + FileStringReplacer.replaceInFile(indexHtmlPath, + Pattern.compile(".*", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + "" + "Build #" + buildNumber + " - " + buildName + "" + ); + } + private void prepareResults(List artifactsTempDirs, @NotNull ImmutableChain chain, @NotNull ChainExecution chainExecution) { copyHistory(artifactsTempDirs, chain.getPlanKey().getKey(), chainExecution.getPlanResultKey().getBuildNumber()); addExecutorInfo(artifactsTempDirs, chain, chainExecution.getPlanResultKey().getBuildNumber()); @@ -207,6 +251,7 @@ private void addExecutorInfo(@NotNull List artifactsTempDirs, @NotNull Imm artifactsTempDirs.forEach(executorInfo::invoke); } + /** * Returns the base url of bamboo server. */ diff --git a/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java b/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java index a9eb406..32a413b 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java @@ -3,17 +3,19 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; import io.qameta.allure.bamboo.info.AllurePlugins; -import io.qameta.allure.bamboo.util.Downloader; +import io.qameta.allure.bamboo.util.FileStringReplacer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; import java.io.File; +import java.io.FileReader; import java.io.IOException; import java.net.URL; import java.nio.file.Path; import java.util.Collection; import java.util.LinkedList; +import java.util.regex.Pattern; import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; @@ -49,13 +51,10 @@ AllureGenerateResult generate(Collection sourceDirs, Path targetDir) { } } - - @SuppressWarnings("ResultOfMethodCallIgnored") public void setCustomLogo(String logoUrl) { final String pluginName = "custom-logo-plugin"; final String allureConfigFileName = "allure.yml"; - final String logoOriginalName = "custom-logo.svg"; - final String logoBackupName = logoOriginalName + "bkp"; + final String cssFileName = "styles.css"; Path rootPath = this.cmdPath.getParent().getParent(); Path configFolder = rootPath.resolve("config"); @@ -70,12 +69,23 @@ public void setCustomLogo(String logoUrl) { if (ap.registerPlugin(pluginName)) { objectMapper.writeValue(configFile, ap); } - /// Backup the original one + //Setting new Logo URL srcLogoUrl = fromPath(logoUrl).build().toURL(); - File bkp = logoPluginFolder.resolve(logoBackupName).toFile(); - logoPluginFolder.resolve(logoOriginalName).toFile().renameTo(bkp); - /// Replace with the new one - Downloader.download(srcLogoUrl, logoPluginFolder.resolve(logoOriginalName)); + FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), + Pattern.compile("url\\('.+'\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + "url(" + srcLogoUrl.toString() + ")" + ); + + // aligning logo to center + FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), + Pattern.compile("(?<=\\s )left",Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + "center" + ); + // removing margin + FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), + Pattern.compile("10px",Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + "0px" + ); } catch (IOException e) { LOGGER.error(e.toString()); diff --git a/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Statistic.java b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Statistic.java new file mode 100644 index 0000000..241856b --- /dev/null +++ b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Statistic.java @@ -0,0 +1,168 @@ + +package io.qameta.allure.bamboo.info.allurewidgets.summary; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class Statistic { + + @SerializedName("failed") + @Expose + private Integer failed; + @SerializedName("broken") + @Expose + private Integer broken; + @SerializedName("skipped") + @Expose + private Integer skipped; + @SerializedName("passed") + @Expose + private Integer passed; + @SerializedName("unknown") + @Expose + private Integer unknown; + @SerializedName("total") + @Expose + private Integer total; + + /** + * No args constructor for use in serialization + * + */ + public Statistic() { + } + + /** + * + * @param broken + * @param total + * @param failed + * @param passed + * @param skipped + * @param unknown + */ + public Statistic(Integer failed, Integer broken, Integer skipped, Integer passed, Integer unknown, Integer total) { + super(); + this.failed = failed; + this.broken = broken; + this.skipped = skipped; + this.passed = passed; + this.unknown = unknown; + this.total = total; + } + + public Integer getFailed() { + return failed; + } + + public void setFailed(Integer failed) { + this.failed = failed; + } + + public Statistic withFailed(Integer failed) { + this.failed = failed; + return this; + } + + public Integer getBroken() { + return broken; + } + + public void setBroken(Integer broken) { + this.broken = broken; + } + + public Statistic withBroken(Integer broken) { + this.broken = broken; + return this; + } + + public Integer getSkipped() { + return skipped; + } + + public void setSkipped(Integer skipped) { + this.skipped = skipped; + } + + public Statistic withSkipped(Integer skipped) { + this.skipped = skipped; + return this; + } + + public Integer getPassed() { + return passed; + } + + public void setPassed(Integer passed) { + this.passed = passed; + } + + public Statistic withPassed(Integer passed) { + this.passed = passed; + return this; + } + + public Integer getUnknown() { + return unknown; + } + + public void setUnknown(Integer unknown) { + this.unknown = unknown; + } + + public Statistic withUnknown(Integer unknown) { + this.unknown = unknown; + return this; + } + + public Integer getTotal() { + return total; + } + + public void setTotal(Integer total) { + this.total = total; + } + + public Statistic withTotal(Integer total) { + this.total = total; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Statistic.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("failed"); + sb.append('='); + sb.append(((this.failed == null)?"":this.failed)); + sb.append(','); + sb.append("broken"); + sb.append('='); + sb.append(((this.broken == null)?"":this.broken)); + sb.append(','); + sb.append("skipped"); + sb.append('='); + sb.append(((this.skipped == null)?"":this.skipped)); + sb.append(','); + sb.append("passed"); + sb.append('='); + sb.append(((this.passed == null)?"":this.passed)); + sb.append(','); + sb.append("unknown"); + sb.append('='); + sb.append(((this.unknown == null)?"":this.unknown)); + sb.append(','); + sb.append("total"); + sb.append('='); + sb.append(((this.total == null)?"":this.total)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + +} diff --git a/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Summary.java b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Summary.java new file mode 100644 index 0000000..9c38a03 --- /dev/null +++ b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Summary.java @@ -0,0 +1,125 @@ + +package io.qameta.allure.bamboo.info.allurewidgets.summary; + +import java.util.List; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class Summary { + + @SerializedName("reportName") + @Expose + private String reportName; + @SerializedName("testRuns") + @Expose + private List testRuns = null; + @SerializedName("statistic") + @Expose + private Statistic statistic; + @SerializedName("time") + @Expose + private Time time; + + /** + * No args constructor for use in serialization + * + */ + public Summary() { + } + + /** + * + * @param statistic + * @param reportName + * @param time + * @param testRuns + */ + public Summary(String reportName, List testRuns, Statistic statistic, Time time) { + super(); + this.reportName = reportName; + this.testRuns = testRuns; + this.statistic = statistic; + this.time = time; + } + + public String getReportName() { + return reportName; + } + + public void setReportName(String reportName) { + this.reportName = reportName; + } + + public Summary withReportName(String reportName) { + this.reportName = reportName; + return this; + } + + public List getTestRuns() { + return testRuns; + } + + public void setTestRuns(List testRuns) { + this.testRuns = testRuns; + } + + public Summary withTestRuns(List testRuns) { + this.testRuns = testRuns; + return this; + } + + public Statistic getStatistic() { + return statistic; + } + + public void setStatistic(Statistic statistic) { + this.statistic = statistic; + } + + public Summary withStatistic(Statistic statistic) { + this.statistic = statistic; + return this; + } + + public Time getTime() { + return time; + } + + public void setTime(Time time) { + this.time = time; + } + + public Summary withTime(Time time) { + this.time = time; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Summary.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("reportName"); + sb.append('='); + sb.append(((this.reportName == null)?"":this.reportName)); + sb.append(','); + sb.append("testRuns"); + sb.append('='); + sb.append(((this.testRuns == null)?"":this.testRuns)); + sb.append(','); + sb.append("statistic"); + sb.append('='); + sb.append(((this.statistic == null)?"":this.statistic)); + sb.append(','); + sb.append("time"); + sb.append('='); + sb.append(((this.time == null)?"":this.time)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + +} diff --git a/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Time.java b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Time.java new file mode 100644 index 0000000..1ae95ce --- /dev/null +++ b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Time.java @@ -0,0 +1,168 @@ + +package io.qameta.allure.bamboo.info.allurewidgets.summary; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class Time { + + @SerializedName("start") + @Expose + private Long start; + @SerializedName("stop") + @Expose + private Long stop; + @SerializedName("duration") + @Expose + private Integer duration; + @SerializedName("minDuration") + @Expose + private Integer minDuration; + @SerializedName("maxDuration") + @Expose + private Integer maxDuration; + @SerializedName("sumDuration") + @Expose + private Integer sumDuration; + + /** + * No args constructor for use in serialization + * + */ + public Time() { + } + + /** + * + * @param duration + * @param sumDuration + * @param minDuration + * @param stop + * @param start + * @param maxDuration + */ + public Time(Long start, Long stop, Integer duration, Integer minDuration, Integer maxDuration, Integer sumDuration) { + super(); + this.start = start; + this.stop = stop; + this.duration = duration; + this.minDuration = minDuration; + this.maxDuration = maxDuration; + this.sumDuration = sumDuration; + } + + public Long getStart() { + return start; + } + + public void setStart(Long start) { + this.start = start; + } + + public Time withStart(Long start) { + this.start = start; + return this; + } + + public Long getStop() { + return stop; + } + + public void setStop(Long stop) { + this.stop = stop; + } + + public Time withStop(Long stop) { + this.stop = stop; + return this; + } + + public Integer getDuration() { + return duration; + } + + public void setDuration(Integer duration) { + this.duration = duration; + } + + public Time withDuration(Integer duration) { + this.duration = duration; + return this; + } + + public Integer getMinDuration() { + return minDuration; + } + + public void setMinDuration(Integer minDuration) { + this.minDuration = minDuration; + } + + public Time withMinDuration(Integer minDuration) { + this.minDuration = minDuration; + return this; + } + + public Integer getMaxDuration() { + return maxDuration; + } + + public void setMaxDuration(Integer maxDuration) { + this.maxDuration = maxDuration; + } + + public Time withMaxDuration(Integer maxDuration) { + this.maxDuration = maxDuration; + return this; + } + + public Integer getSumDuration() { + return sumDuration; + } + + public void setSumDuration(Integer sumDuration) { + this.sumDuration = sumDuration; + } + + public Time withSumDuration(Integer sumDuration) { + this.sumDuration = sumDuration; + return this; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(Time.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); + sb.append("start"); + sb.append('='); + sb.append(((this.start == null)?"":this.start)); + sb.append(','); + sb.append("stop"); + sb.append('='); + sb.append(((this.stop == null)?"":this.stop)); + sb.append(','); + sb.append("duration"); + sb.append('='); + sb.append(((this.duration == null)?"":this.duration)); + sb.append(','); + sb.append("minDuration"); + sb.append('='); + sb.append(((this.minDuration == null)?"":this.minDuration)); + sb.append(','); + sb.append("maxDuration"); + sb.append('='); + sb.append(((this.maxDuration == null)?"":this.maxDuration)); + sb.append(','); + sb.append("sumDuration"); + sb.append('='); + sb.append(((this.sumDuration == null)?"":this.sumDuration)); + sb.append(','); + if (sb.charAt((sb.length()- 1)) == ',') { + sb.setCharAt((sb.length()- 1), ']'); + } else { + sb.append(']'); + } + return sb.toString(); + } + +} diff --git a/src/main/java/io/qameta/allure/bamboo/util/FileStringReplacer.java b/src/main/java/io/qameta/allure/bamboo/util/FileStringReplacer.java new file mode 100644 index 0000000..24fb631 --- /dev/null +++ b/src/main/java/io/qameta/allure/bamboo/util/FileStringReplacer.java @@ -0,0 +1,25 @@ +package io.qameta.allure.bamboo.util; + +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.regex.Pattern; + +public class FileStringReplacer { + + public static void replaceInFile(Path filePath, String oldString, String newString) throws IOException { + String content = new String(Files.readAllBytes(filePath), StandardCharsets.UTF_8); + content = content.replaceAll(oldString, newString); + Files.write(filePath, content.getBytes(StandardCharsets.UTF_8)); + } + + public static void replaceInFile(Path filePath, @NotNull Pattern pattern, String newString) throws IOException { + String content = new String(Files.readAllBytes(filePath), StandardCharsets.UTF_8); + content = pattern.matcher(content).replaceAll(newString); + Files.write(filePath, content.getBytes(StandardCharsets.UTF_8)); + } + +} diff --git a/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java b/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java index 140faa4..ac7cd57 100644 --- a/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java +++ b/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java @@ -1,5 +1,6 @@ package io.qameta.allure.bamboo.util; +import net.lingala.zip4j.ZipFile; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.ArchiveInputStream; @@ -11,9 +12,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.nio.file.*; + +import static java.nio.file.Files.*; public class ZipUtil { @@ -43,5 +44,12 @@ public static void unzip(@NotNull Path zipFilePath, String outputDir) throws IOE } } - + public static void zipFolder(@NotNull Path srcFolder, @NotNull Path targetDir) throws IOException { + Path zipReportTmpDir = createTempDirectory("tmp_allure_report"); + Path zipReport = zipReportTmpDir.resolve("report.zip"); + try (ZipFile zp = new ZipFile(zipReport.toFile())) { + zp.addFolder(srcFolder.toFile()); + } + move(zipReport, targetDir, StandardCopyOption.REPLACE_EXISTING); + } } diff --git a/src/main/resources/templates/viewAllureReport.ftl b/src/main/resources/templates/viewAllureReport.ftl index 37d10c7..281b6ea 100644 --- a/src/main/resources/templates/viewAllureReport.ftl +++ b/src/main/resources/templates/viewAllureReport.ftl @@ -2,6 +2,7 @@ [#assign reportUrl = "${baseUrl}/plugins/servlet/allure/report/${planKey}/${buildNumber}/"] +[#assign reportZipUrl = "${baseUrl}/plugins/servlet/allure/report/${planKey}/${buildNumber}/report.zip"] [@ui.header pageKey='buildResult.changes.title' object='${immutablePlan.name} ${resultsSummary.buildNumber}' title=true/] -Expand +Expand  +Download  \ No newline at end of file From d873df735e12a8c44f0929ac29e392f36f98ef8a Mon Sep 17 00:00:00 2001 From: Manuel Lara Date: Fri, 19 Aug 2022 16:40:51 -0300 Subject: [PATCH 07/15] > Change Version: 2.0, because the change in this version is major. Signed-off-by: Manuel Lara --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 641e6c2..3e4675c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ 4.0.0 io.qameta.allure allure-bamboo - 1.13-SNAPSHOT + 2.00 Allure for Bamboo Allure reports right in deployment plans in Bamboo atlassian-plugin From e143ff0d6ca32bd98a5ae63db46aa2a70b6f95c8 Mon Sep 17 00:00:00 2001 From: Manuel Lara Date: Fri, 19 Aug 2022 16:43:01 -0300 Subject: [PATCH 08/15] Revert "> Change Version: 2.0, because the change in this version is major." This reverts commit d873df735e12a8c44f0929ac29e392f36f98ef8a. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3e4675c..641e6c2 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ 4.0.0 io.qameta.allure allure-bamboo - 2.00 + 1.13-SNAPSHOT Allure for Bamboo Allure reports right in deployment plans in Bamboo atlassian-plugin From a27d16c65b5df3ea87674539296a4e1e79b7ba7b Mon Sep 17 00:00:00 2001 From: Manuel Lara Date: Fri, 19 Aug 2022 16:46:23 -0300 Subject: [PATCH 09/15] Revert "Revert "> Change Version: 2.0, because the change in this version is major."" This reverts commit e143ff0d6ca32bd98a5ae63db46aa2a70b6f95c8. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 641e6c2..3e4675c 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ 4.0.0 io.qameta.allure allure-bamboo - 1.13-SNAPSHOT + 2.00 Allure for Bamboo Allure reports right in deployment plans in Bamboo atlassian-plugin From b74b5a7d0fd880f87cd9cb934a47fcf367476310 Mon Sep 17 00:00:00 2001 From: Manuel Lara Date: Tue, 10 Jan 2023 19:19:09 -0300 Subject: [PATCH 10/15] > Change Version: 2.0 to 2.0-SNAPSHOT > amps.version to 8.0.3-89c970d65 Signed-off-by: Manuel Lara --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3e4675c..1338b68 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ 4.0.0 io.qameta.allure allure-bamboo - 2.00 + 2.00-SNAPSHOT Allure for Bamboo Allure reports right in deployment plans in Bamboo atlassian-plugin @@ -15,7 +15,7 @@ https://github.com/allure-framework - 8.0.2 + 8.0.3-89c970d65 7.1.4 ${bamboo.version} 1.8 From cc507ac623418e8d16700b5b15b8df11c592a179 Mon Sep 17 00:00:00 2001 From: Dmitry Baev Date: Wed, 9 Nov 2022 22:29:41 +0400 Subject: [PATCH 11/15] update license Signed-off-by: Manuel Lara --- LICENSE | 208 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 198 insertions(+), 10 deletions(-) diff --git a/LICENSE b/LICENSE index c0686b2..e56c86d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,13 +1,201 @@ -Copyright 2014 YANDEX + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Licensed 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 + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION -http://www.apache.org/licenses/LICENSE-2.0 + 1. Definitions. -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. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016-2022 Qameta Software OÃœ + + Licensed 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. From d35102cb04b31cd740a44c8a2c08928b9e17eac6 Mon Sep 17 00:00:00 2001 From: Manuel Lara Date: Wed, 11 Jan 2023 12:32:41 -0300 Subject: [PATCH 12/15] > Fixes Signed-off-by: Manuel Lara --- pom.xml | 23 +++-------- .../allure/bamboo/AllureArtifactsManager.java | 2 - .../bamboo/AllureBuildCompleteAction.java | 39 +++++++++---------- .../allure/bamboo/AllureBuildConfig.java | 6 ++- .../allure/bamboo/AllureDownloader.java | 6 ++- .../allure/bamboo/AllureExecutable.java | 1 - .../bamboo/AllureExecutableProvider.java | 1 - .../allure/bamboo/AllureGlobalConfig.java | 7 +++- .../allure/bamboo/AllureSettingsManager.java | 7 +++- .../info/allurewidgets/summary/Summary.java | 15 ++++--- .../info/allurewidgets/summary/Time.java | 18 ++++----- .../qameta/allure/bamboo/util/Downloader.java | 1 - .../io/qameta/allure/bamboo/util/ZipUtil.java | 10 +++-- 13 files changed, 66 insertions(+), 70 deletions(-) diff --git a/pom.xml b/pom.xml index 1338b68..0cd425e 100644 --- a/pom.xml +++ b/pom.xml @@ -40,22 +40,17 @@ com.fasterxml.jackson.dataformat jackson-dataformat-yaml - 2.13.3 - - - com.google.code.gson - gson - 2.9.0 + 2.14.0 com.fasterxml.jackson.core jackson-databind - 2.13.3 + 2.14.0 org.buildobjects jproc - 2.8.0 + 2.8.2 com.atlassian.bamboo @@ -63,10 +58,6 @@ ${bamboo.version} provided - - com.google.code.gson - gson - commons-beanutils commons-beanutils @@ -130,7 +121,7 @@ net.lingala.zip4j zip4j - 2.11.1 + 2.11.2 org.slf4j @@ -183,7 +174,7 @@ org.mockito mockito-core - 4.6.1 + 4.11.0 test @@ -199,10 +190,6 @@ ${plugin.testrunner.version} test - - com.google.code.gson - gson - commons-beanutils commons-beanutils diff --git a/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java b/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java index 0881476..bd8fc76 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java @@ -345,8 +345,6 @@ private Map getArtifactHandlersConfig(BuildDefinition buildDefin final Map config = artifactHandlersService.getRuntimeConfiguration(); final Map planCustomConfiguration = buildDefinition.getCustomConfiguration(); if (ArtifactHandlingUtils.isCustomArtifactHandlingConfigured(planCustomConfiguration)) { - // This hacky way it's compatible with both Bamboo 5.x and Bamboo 6.x - //TODO is it compatible with 7.x?? final Collector, ?, Map> toMap = toMap(Map.Entry::getKey, Map.Entry::getValue); final Predicate> isArtifactHandler = e -> e.getKey().startsWith(ARTIFACT_HANDLERS_CONFIG_PREFIX); final Predicate> isNotHandlerSwitch = e -> SHARED_NON_SHARED_ONOFF_OPTION_NAME.values().stream().noneMatch(o -> e.getKey().endsWith(o)); diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java index fe74d53..632297f 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java @@ -10,6 +10,7 @@ import com.atlassian.bamboo.resultsummary.ResultsSummaryManager; import com.atlassian.bamboo.v2.build.BaseConfigurablePlugin; import com.atlassian.spring.container.ContainerManager; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import com.google.gson.JsonParser; import io.qameta.allure.bamboo.info.AddExecutorInfo; @@ -22,14 +23,23 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.*; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.Writer; import java.net.URL; import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.regex.Pattern; @@ -119,8 +129,6 @@ public void execute(@NotNull ImmutableChain chain, @NotNull ChainResultsSummary LOGGER.info("Allure has been generated successfully for {}", chain.getName()); artifactsManager.uploadReportArtifacts(chain, chainResultsSummary, allureReportDir) .ifPresent(result -> result.dumpToCustomData(customBuildData)); - - } } catch (Exception e) { LOGGER.error("Failed to build allure report for {}", chain.getName(), e); @@ -131,24 +139,14 @@ public void execute(@NotNull ImmutableChain chain, @NotNull ChainResultsSummary } } - /** - * I'm a friend, and it's a gift for all you that wants to customize allure report for your projects. :) - * @param allureReportDir - * @param buildNumber - * @param buildName - * @throws IOException - */ private void finalize(@NotNull File allureReportDir, int buildNumber, String buildName) throws IOException { //////////////////// // Update Report Name (It is the way now) Path widgetsJsonPath = Paths.get(allureReportDir.getAbsolutePath()).resolve("widgets").resolve("summary.json"); - Gson gson = new Gson(); - Summary summary = gson.fromJson(new FileReader(widgetsJsonPath.toFile()), Summary.class); - summary.setReportName("Build #" + buildNumber + " - " + buildName); - Writer json = new FileWriter(widgetsJsonPath.toFile()); - gson.toJson(summary, Summary.class, json); - json.flush(); - json.close(); + ObjectMapper mapper = new ObjectMapper(); + Summary summary = mapper.readValue(widgetsJsonPath.toFile(), Summary.class); + summary.setReportName(String.format("Build %s - %s", buildNumber, buildName)); + mapper.writeValue(widgetsJsonPath.toFile(), summary); //////////////////// // Deleting title from Logo Path appJsPath = Paths.get(allureReportDir.getAbsolutePath()).resolve("app.js"); @@ -161,7 +159,7 @@ private void finalize(@NotNull File allureReportDir, int buildNumber, String bui Path indexHtmlPath = Paths.get(allureReportDir.getAbsolutePath()).resolve("index.html"); FileStringReplacer.replaceInFile(indexHtmlPath, Pattern.compile(".*", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), - "" + "Build #" + buildNumber + " - " + buildName + "" + String.format(" Build %s - %s ", buildNumber, buildName) ); } @@ -208,11 +206,12 @@ private Optional getLastBuildNumberWithHistory(String planKey, int buil private boolean historyArtifactExists(String planKey, int buildId) { String artifactUrl = getHistoryArtifactUrl("history.json", planKey, buildId); + ObjectMapper mapper = new ObjectMapper(); JsonParser parser = new JsonParser(); try { final Path historyTmpFile = createTempFile("history", ".json"); Downloader.download(new URL(artifactUrl), historyTmpFile); - parser.parse(new FileReader(historyTmpFile.toFile())); + mapper.readValue(historyTmpFile.toFile(), Object.class); return true; } catch (Exception e) { LOGGER.info("Cannot connect to artifact or the artifact is not valid {}.", artifactUrl, e); diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java index f0917d7..197efa6 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java @@ -6,7 +6,11 @@ import java.io.Serializable; import java.util.Map; -import static io.qameta.allure.bamboo.AllureConstants.*; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_ARTIFACT_NAME; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_ENABLED; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_EXECUTABLE; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_FAILED_ONLY; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CUSTOM_LOGO_PATH; import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; import static java.util.Optional.ofNullable; diff --git a/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java b/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java index ef4eff7..b4de59a 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java @@ -6,10 +6,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.*; +import java.io.File; +import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; -import java.nio.file.*; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Optional; import static java.nio.file.Files.createTempFile; diff --git a/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java b/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java index 32a413b..22ac4b6 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java @@ -9,7 +9,6 @@ import javax.annotation.Nonnull; import java.io.File; -import java.io.FileReader; import java.io.IOException; import java.net.URL; import java.nio.file.Path; diff --git a/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java b/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java index 5cc8b66..fa7e21b 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java @@ -4,7 +4,6 @@ import static java.util.Objects.requireNonNull; import static java.util.regex.Pattern.compile; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/io/qameta/allure/bamboo/AllureGlobalConfig.java b/src/main/java/io/qameta/allure/bamboo/AllureGlobalConfig.java index 1256701..6de9875 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureGlobalConfig.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureGlobalConfig.java @@ -7,7 +7,12 @@ import java.io.Serializable; import java.util.Map; -import static io.qameta.allure.bamboo.AllureConstants.*; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_DOWNLOAD_CLI_URL; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_DOWNLOAD_ENABLED; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_DOWNLOAD_URL; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_ENABLED_BY_DEFAULT; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_LOCAL_STORAGE; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CUSTOM_LOGO_ENABLED; import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; import static java.lang.Boolean.parseBoolean; diff --git a/src/main/java/io/qameta/allure/bamboo/AllureSettingsManager.java b/src/main/java/io/qameta/allure/bamboo/AllureSettingsManager.java index 7ed0bab..cd6d223 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureSettingsManager.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureSettingsManager.java @@ -3,7 +3,12 @@ import com.atlassian.sal.api.pluginsettings.PluginSettings; import com.atlassian.sal.api.pluginsettings.PluginSettingsFactory; -import static io.qameta.allure.bamboo.AllureConstants.*; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_DOWNLOAD_CLI_URL; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_DOWNLOAD_ENABLED; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_DOWNLOAD_URL; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_ENABLED_BY_DEFAULT; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CONFIG_LOCAL_STORAGE; +import static io.qameta.allure.bamboo.AllureConstants.ALLURE_CUSTOM_LOGO_ENABLED; public class AllureSettingsManager { private final PluginSettings settings; diff --git a/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Summary.java b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Summary.java index 9c38a03..cfc0ff7 100644 --- a/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Summary.java +++ b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Summary.java @@ -2,6 +2,7 @@ package io.qameta.allure.bamboo.info.allurewidgets.summary; import java.util.List; + import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; @@ -22,13 +23,11 @@ public class Summary { /** * No args constructor for use in serialization - * */ public Summary() { } /** - * * @param statistic * @param reportName * @param time @@ -100,22 +99,22 @@ public String toString() { sb.append(Summary.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); sb.append("reportName"); sb.append('='); - sb.append(((this.reportName == null)?"":this.reportName)); + sb.append(((this.reportName == null) ? "" : this.reportName)); sb.append(','); sb.append("testRuns"); sb.append('='); - sb.append(((this.testRuns == null)?"":this.testRuns)); + sb.append(((this.testRuns == null) ? "" : this.testRuns)); sb.append(','); sb.append("statistic"); sb.append('='); - sb.append(((this.statistic == null)?"":this.statistic)); + sb.append(((this.statistic == null) ? "" : this.statistic)); sb.append(','); sb.append("time"); sb.append('='); - sb.append(((this.time == null)?"":this.time)); + sb.append(((this.time == null) ? "" : this.time)); sb.append(','); - if (sb.charAt((sb.length()- 1)) == ',') { - sb.setCharAt((sb.length()- 1), ']'); + if (sb.charAt((sb.length() - 1)) == ',') { + sb.setCharAt((sb.length() - 1), ']'); } else { sb.append(']'); } diff --git a/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Time.java b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Time.java index 1ae95ce..c557096 100644 --- a/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Time.java +++ b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Time.java @@ -27,13 +27,11 @@ public class Time { /** * No args constructor for use in serialization - * */ public Time() { } /** - * * @param duration * @param sumDuration * @param minDuration @@ -135,30 +133,30 @@ public String toString() { sb.append(Time.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('['); sb.append("start"); sb.append('='); - sb.append(((this.start == null)?"":this.start)); + sb.append(((this.start == null) ? "" : this.start)); sb.append(','); sb.append("stop"); sb.append('='); - sb.append(((this.stop == null)?"":this.stop)); + sb.append(((this.stop == null) ? "" : this.stop)); sb.append(','); sb.append("duration"); sb.append('='); - sb.append(((this.duration == null)?"":this.duration)); + sb.append(((this.duration == null) ? "" : this.duration)); sb.append(','); sb.append("minDuration"); sb.append('='); - sb.append(((this.minDuration == null)?"":this.minDuration)); + sb.append(((this.minDuration == null) ? "" : this.minDuration)); sb.append(','); sb.append("maxDuration"); sb.append('='); - sb.append(((this.maxDuration == null)?"":this.maxDuration)); + sb.append(((this.maxDuration == null) ? "" : this.maxDuration)); sb.append(','); sb.append("sumDuration"); sb.append('='); - sb.append(((this.sumDuration == null)?"":this.sumDuration)); + sb.append(((this.sumDuration == null) ? "" : this.sumDuration)); sb.append(','); - if (sb.charAt((sb.length()- 1)) == ',') { - sb.setCharAt((sb.length()- 1), ']'); + if (sb.charAt((sb.length() - 1)) == ',') { + sb.setCharAt((sb.length() - 1), ']'); } else { sb.append(']'); } diff --git a/src/main/java/io/qameta/allure/bamboo/util/Downloader.java b/src/main/java/io/qameta/allure/bamboo/util/Downloader.java index 371163f..646189f 100644 --- a/src/main/java/io/qameta/allure/bamboo/util/Downloader.java +++ b/src/main/java/io/qameta/allure/bamboo/util/Downloader.java @@ -1,6 +1,5 @@ package io.qameta.allure.bamboo.util; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; diff --git a/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java b/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java index ac7cd57..9f36e58 100644 --- a/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java +++ b/src/main/java/io/qameta/allure/bamboo/util/ZipUtil.java @@ -7,14 +7,16 @@ import org.apache.commons.compress.archivers.ArchiveStreamFactory; import org.apache.commons.compress.utils.IOUtils; import org.jetbrains.annotations.NotNull; - import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.file.*; - -import static java.nio.file.Files.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import static java.nio.file.Files.createTempDirectory; +import static java.nio.file.Files.move; public class ZipUtil { From a1ddb23c7653b8d0e386dad282d2e85867cae931 Mon Sep 17 00:00:00 2001 From: Manuel Lara Date: Thu, 27 Apr 2023 08:43:12 -0300 Subject: [PATCH 13/15] > Fixes: - Fixed custom logo error with multiple plans same agent. - Improved logo customization options with support for base64 URLs and various file extensions. Signed-off-by: Manuel Lara --- .../bamboo/AllureBuildCompleteAction.java | 2 +- .../allure/bamboo/AllureBuildConfig.java | 4 +-- .../allure/bamboo/AllureExecutable.java | 32 +++++++++++++++---- .../bamboo/AllureExecutableProvider.java | 8 +++-- src/main/resources/allure-bamboo.properties | 2 +- .../editAllureBambooConfiguration.ftl | 4 +-- .../bamboo/AllureExecutableProviderTest.java | 9 ++++-- 7 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java index 632297f..3ffbedf 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java @@ -103,7 +103,7 @@ public void execute(@NotNull ImmutableChain chain, @NotNull ChainResultsSummary LOGGER.info("Trying to get executable by name {} for {}", executable, chain.getName()); final AllureExecutable allure = allureExecutable.provide(globalConfig, executable).orElseThrow(() -> - new RuntimeException("Failed to find Allure executable by name " + executable)); + new RuntimeException("Failed to find Allure executable by name " + executable)).getCopy(); LOGGER.info("Starting artifacts downloading into {} for {}", artifactsTempDir.getPath(), chain.getName()); final Collection artifactsPaths = artifactsManager.downloadAllArtifactsTo( diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java index 197efa6..33e5026 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java @@ -30,9 +30,7 @@ private AllureBuildConfig(String executable, String enabled, String onlyForFaile this.enabled = isEmpty(enabled) ? FALSE : Boolean.parseBoolean(enabled); this.executable = executable; this.artifactName = artifactName; - // If the URL is not a valid URL it will be omitted - UrlValidator urlValidator = new UrlValidator(); - this.logoUrl = urlValidator.isValid(logoUrl) ? logoUrl : AllureBuildConfig.DEFAULT_CUSTOM_LOGO_URL; + this.logoUrl = !logoUrl.isEmpty() ? logoUrl : AllureBuildConfig.DEFAULT_CUSTOM_LOGO_URL; } static AllureBuildConfig fromContext(Map context) { diff --git a/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java b/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java index 22ac4b6..3406f89 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java @@ -10,15 +10,15 @@ import javax.annotation.Nonnull; import java.io.File; import java.io.IOException; -import java.net.URL; import java.nio.file.Path; import java.util.Collection; import java.util.LinkedList; import java.util.regex.Pattern; +import static java.nio.file.Files.createTempDirectory; import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; -import static javax.ws.rs.core.UriBuilder.fromPath; +import static org.apache.commons.io.FileUtils.copyDirectoryToDirectory; class AllureExecutable { private static final Logger LOGGER = LoggerFactory.getLogger(AllureExecutable.class); @@ -69,20 +69,24 @@ public void setCustomLogo(String logoUrl) { objectMapper.writeValue(configFile, ap); } //Setting new Logo - URL srcLogoUrl = fromPath(logoUrl).build().toURL(); FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), Pattern.compile("url\\('.+'\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), - "url(" + srcLogoUrl.toString() + ")" + "url(" + logoUrl + ")" ); // aligning logo to center FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), - Pattern.compile("(?<=\\s )left",Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + Pattern.compile("(?<=\\s )left", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), "center" ); + // fit logo to area + FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), + Pattern.compile("(?<=\\s )!important;", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + "!important; background-size: contain !important;" + ); // removing margin FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), - Pattern.compile("10px",Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + Pattern.compile("10px", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), "0px" ); @@ -92,6 +96,22 @@ public void setCustomLogo(String logoUrl) { } } + public AllureExecutable getCopy() throws IOException { + String binary = this.cmdPath.getFileName().toString(); + String binFolder = this.cmdPath.getParent().getFileName().toString(); + Path rootPath = this.cmdPath.getParent().getParent(); + Path rootFolderName = rootPath.getFileName(); + Path copyPath = createTempDirectory(rootFolderName.toString()); + copyDirectoryToDirectory(rootPath.toFile(), copyPath.toFile()); + + return new AllureExecutable(copyPath + .resolve(rootFolderName.toString()) + .resolve(binFolder) + .resolve(binary), + this.cmdLine + ); + } + Path getCmdPath() { return cmdPath; } diff --git a/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java b/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java index fa7e21b..667d34a 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java @@ -1,12 +1,15 @@ package io.qameta.allure.bamboo; import com.google.common.annotations.VisibleForTesting; + import static java.util.Objects.requireNonNull; import static java.util.regex.Pattern.compile; + import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Optional; @@ -43,7 +46,8 @@ Optional provide(boolean isDownloadEnabled, String executableN LOGGER.debug("Found allure executable by name '{}': '{}'", executableName, allureHomeDir); final String allureHomeSubDir = Paths.get(allureHomeDir, BINARY_SUBDIR).toString(); final Path cmdPath = Paths.get(allureHomeSubDir, "bin", getAllureExecutableName()); - final AllureExecutable executable = new AllureExecutable(cmdPath, cmdLine); + final AllureExecutable executable; + executable = new AllureExecutable(cmdPath, cmdLine); LOGGER.debug("Checking the existence of the command path for executable '{}': '{}'", executableName, cmdPath); final boolean commandExists = cmdLine.hasCommand(cmdPath.toString()); @@ -54,7 +58,7 @@ Optional provide(boolean isDownloadEnabled, String executableN } else if (isDownloadEnabled) { final Matcher nameMatcher = EXEC_NAME_PATTERN.matcher(executableName); return allureDownloader.downloadAndExtractAllureTo(allureHomeSubDir, - nameMatcher.matches() ? nameMatcher.group(1) : DEFAULT_VERSION) + nameMatcher.matches() ? nameMatcher.group(1) : DEFAULT_VERSION) .map(path -> executable).orElse(null); } return null; diff --git a/src/main/resources/allure-bamboo.properties b/src/main/resources/allure-bamboo.properties index ef3355b..7e12d72 100644 --- a/src/main/resources/allure-bamboo.properties +++ b/src/main/resources/allure-bamboo.properties @@ -44,4 +44,4 @@ build.allure.title=Allure Report buildResult.allure.title=Allure Report allure.config.logo.enabled.label=Enable report custom logo -custom.allure.logo.url.label=Custom logo URL (svg) \ No newline at end of file +custom.allure.logo.url.label=Custom logo diff --git a/src/main/resources/templates/editAllureBambooConfiguration.ftl b/src/main/resources/templates/editAllureBambooConfiguration.ftl index a4bbe48..a0ab169 100644 --- a/src/main/resources/templates/editAllureBambooConfiguration.ftl +++ b/src/main/resources/templates/editAllureBambooConfiguration.ftl @@ -9,6 +9,6 @@ [@ww.textfield labelKey="custom.allure.artifact.name.label" name="custom.allure.artifact.name" required="false"/] - [@ww.textfield labelKey="custom.allure.logo.url.label" name="custom.allure.logo.url" required="false"/] + [@ww.textarea labelKey="custom.allure.logo.url.label" name="custom.allure.logo.url" required="false"/] -[/@ui.bambooSection] \ No newline at end of file +[/@ui.bambooSection] diff --git a/src/test/java/io/qameta/allure/bamboo/AllureExecutableProviderTest.java b/src/test/java/io/qameta/allure/bamboo/AllureExecutableProviderTest.java index 87891fe..e1a1784 100644 --- a/src/test/java/io/qameta/allure/bamboo/AllureExecutableProviderTest.java +++ b/src/test/java/io/qameta/allure/bamboo/AllureExecutableProviderTest.java @@ -7,6 +7,8 @@ import org.mockito.Mock; import org.mockito.junit.MockitoRule; +import java.io.File; +import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Optional; @@ -16,6 +18,7 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.contains; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.junit.MockitoJUnit.rule; @@ -33,6 +36,8 @@ public class AllureExecutableProviderTest { @Mock private AllureCommandLineSupport cmdLine; @InjectMocks + private AllureExecutable allureExecutable; + @InjectMocks private AllureExecutableProvider provider; private AllureGlobalConfig config; private Path allureCmdPath; @@ -88,7 +93,7 @@ public void itShouldProvideExecutableForUnix() throws Exception { } @Test - public void itShouldProvideExecutableForWindows() throws Exception { + public void itShouldProvideExecutableForWindows() { when(cmdLine.hasCommand(allureBatCmdPath.toString())).thenReturn(true); when(cmdLine.isWindows()).thenReturn(true); @@ -102,4 +107,4 @@ private Optional provide(String executableName) { when(executablesManager.getExecutableByName(executableName)).thenReturn(Optional.of(homeDir)); return provider.provide(config, executableName); } -} \ No newline at end of file +} From f6de029d30dd70014bc5cffd47df3d224bb29fc8 Mon Sep 17 00:00:00 2001 From: Manuel Lara Date: Thu, 27 Apr 2023 09:31:53 -0300 Subject: [PATCH 14/15] > Fixes: - Fixed custom logo error with multiple plans same agent. - Improved logo customization options with support for base64 URLs and various file extensions. Signed-off-by: Manuel Lara --- .../bamboo/AllureBuildCompleteAction.java | 7 ++-- .../allure/bamboo/AllureBuildConfig.java | 4 +-- .../allure/bamboo/AllureExecutable.java | 36 ++++++++++++++----- .../editAllureBambooConfiguration.ftl | 4 +-- 4 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java index a8fac57..20f61a6 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java @@ -125,6 +125,9 @@ public void execute(final @NotNull ImmutableChain chain, final AllureExecutable allure = allureExecutable.provide(globalConfig, executable) .orElseThrow(() -> new RuntimeException("Failed to find Allure executable by name " + executable)); + // Creating a copy for customize report + AllureExecutable allureTmp = allure.getCopy(); + LOGGER.info("Starting artifacts downloading into {} for {}", artifactsTempDir.getPath(), chain.getName()); final Collection artifactsPaths = artifactsManager.downloadAllArtifactsTo( chainResultsSummary, artifactsTempDir, buildConfig.getArtifactName()); @@ -137,9 +140,9 @@ public void execute(final @NotNull ImmutableChain chain, // Setting the new logo in the allure libraries before generate the report. if (globalConfig.isCustomLogoEnabled()) { - allure.setCustomLogo(buildConfig.getCustomLogoUrl()); + allureTmp.setCustomLogo(buildConfig.getCustomLogoUrl()); } - allure.generate(artifactsPaths, allureReportDir.toPath()); + allureTmp.generate(artifactsPaths, allureReportDir.toPath()); // Setting report name this.finalizeReport(allureReportDir, chainExecution.getPlanResultKey().getBuildNumber(), chain.getBuildName()); diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java index eff78b2..41c8392 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java @@ -49,9 +49,7 @@ private AllureBuildConfig(final String executable, this.enabled = StringUtils.isEmpty(enabled) ? FALSE : Boolean.parseBoolean(enabled); this.executable = executable; this.artifactName = artifactName; - // If the URL is not a valid URL it will be omitted - final UrlValidator urlValidator = new UrlValidator(); - this.logoUrl = urlValidator.isValid(logoUrl) ? logoUrl : AllureBuildConfig.DEFAULT_CUSTOM_LOGO_URL; + this.logoUrl = !logoUrl.isEmpty() ? logoUrl : AllureBuildConfig.DEFAULT_CUSTOM_LOGO_URL; } static AllureBuildConfig fromContext(final Map context) { diff --git a/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java b/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java index b23a993..b9ce84e 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java @@ -31,9 +31,10 @@ import java.util.LinkedList; import java.util.regex.Pattern; +import static java.nio.file.Files.createTempDirectory; import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; -import static javax.ws.rs.core.UriBuilder.fromPath; +import static org.apache.commons.io.FileUtils.copyDirectoryToDirectory; class AllureExecutable { @@ -87,23 +88,24 @@ public void setCustomLogo(final String logoUrl) { objectMapper.writeValue(configFile, ap); } //Setting new Logo - final URL srcLogoUrl = fromPath(logoUrl).build().toURL(); FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), - Pattern.compile("url\\('.+'\\)", - Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), - "url(" + srcLogoUrl.toString() + ")" + Pattern.compile("url\\('.+'\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + "url(" + logoUrl + ")" ); // aligning logo to center FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), - Pattern.compile("(?<=\\s )left", - Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + Pattern.compile("(?<=\\s )left", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), "center" ); + // fit logo to area + FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), + Pattern.compile("(?<=\\s )!important;", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + "!important; background-size: contain !important;" + ); // removing margin FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), - Pattern.compile("10px", - Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + Pattern.compile("10px", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), "0px" ); @@ -113,6 +115,22 @@ public void setCustomLogo(final String logoUrl) { } } + public AllureExecutable getCopy() throws IOException { + String binary = this.cmdPath.getFileName().toString(); + String binFolder = this.cmdPath.getParent().getFileName().toString(); + Path rootPath = this.cmdPath.getParent().getParent(); + Path rootFolderName = rootPath.getFileName(); + Path copyPath = createTempDirectory(rootFolderName.toString()); + copyDirectoryToDirectory(rootPath.toFile(), copyPath.toFile()); + + return new AllureExecutable(copyPath + .resolve(rootFolderName.toString()) + .resolve(binFolder) + .resolve(binary), + this.cmdLine + ); + } + Path getCmdPath() { return cmdPath; } diff --git a/src/main/resources/templates/editAllureBambooConfiguration.ftl b/src/main/resources/templates/editAllureBambooConfiguration.ftl index a4bbe48..a0ab169 100644 --- a/src/main/resources/templates/editAllureBambooConfiguration.ftl +++ b/src/main/resources/templates/editAllureBambooConfiguration.ftl @@ -9,6 +9,6 @@ [@ww.textfield labelKey="custom.allure.artifact.name.label" name="custom.allure.artifact.name" required="false"/] - [@ww.textfield labelKey="custom.allure.logo.url.label" name="custom.allure.logo.url" required="false"/] + [@ww.textarea labelKey="custom.allure.logo.url.label" name="custom.allure.logo.url" required="false"/] -[/@ui.bambooSection] \ No newline at end of file +[/@ui.bambooSection] From 780ee492c1a1d5f4ef0182e973267eb561ae7d8d Mon Sep 17 00:00:00 2001 From: Manuel Lara Date: Thu, 27 Apr 2023 10:25:46 -0300 Subject: [PATCH 15/15] > Fixes: - Fixed custom logo error with multiple plans same agent. - Improved logo customization options with support for base64 URLs and various file extensions. Signed-off-by: Manuel Lara --- .github/workflows/release.yml | 2 +- .../quality-configs/checkstyle/checkstyle.xml | 14 ++--- .mvn/quality-configs/pmd/pmd.xml | 3 +- .mvn/quality-configs/spotbugs/exclude.xml | 2 +- README.md | 20 +++++-- pom.xml | 8 ++- .../allure/bamboo/AllureArtifactsManager.java | 56 +++++++++---------- .../bamboo/AllureBuildCompleteAction.java | 2 +- .../allure/bamboo/AllureBuildConfig.java | 1 - .../allure/bamboo/AllureDownloader.java | 12 ++-- .../allure/bamboo/AllureExecutable.java | 23 ++++---- .../bamboo/AllureExecutableProvider.java | 2 +- .../allure/bamboo/AllureReportServlet.java | 4 +- .../bamboo/BambooExecutablesManager.java | 2 +- .../info/allurewidgets/summary/Statistic.java | 1 - .../info/allurewidgets/summary/Summary.java | 6 +- .../info/allurewidgets/summary/Time.java | 6 +- .../qameta/allure/bamboo/util/Downloader.java | 22 ++++---- src/main/resources/allure-bamboo.properties | 43 +++++++------- .../templates/editAllureReportConfig.ftl | 32 +++++------ src/main/resources/templates/error.ftl | 20 +++---- .../resources/templates/viewAllureReport.ftl | 16 +++--- src/test/resources/log4j.properties | 6 +- 23 files changed, 156 insertions(+), 147 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4047763..5d8dda1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,7 +2,7 @@ name: Release on: release: - types: [published] + types: [ published ] jobs: build: diff --git a/.mvn/quality-configs/checkstyle/checkstyle.xml b/.mvn/quality-configs/checkstyle/checkstyle.xml index 7bac100..52ef7d5 100644 --- a/.mvn/quality-configs/checkstyle/checkstyle.xml +++ b/.mvn/quality-configs/checkstyle/checkstyle.xml @@ -104,10 +104,10 @@ - - - - + + + + @@ -136,9 +136,9 @@ - - - + + + diff --git a/.mvn/quality-configs/pmd/pmd.xml b/.mvn/quality-configs/pmd/pmd.xml index 8a239f0..f075ea8 100644 --- a/.mvn/quality-configs/pmd/pmd.xml +++ b/.mvn/quality-configs/pmd/pmd.xml @@ -112,7 +112,8 @@ - + diff --git a/.mvn/quality-configs/spotbugs/exclude.xml b/.mvn/quality-configs/spotbugs/exclude.xml index 4fa9242..5fa5c6b 100644 --- a/.mvn/quality-configs/spotbugs/exclude.xml +++ b/.mvn/quality-configs/spotbugs/exclude.xml @@ -13,7 +13,7 @@ you will have to use @NotNull annotation, which contradict with original contract (actually not, because guava intend weaker semantics). So disable this check to be able to properly use nullability annotations --> - + diff --git a/README.md b/README.md index 208042d..708bd79 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,29 @@ ## Allure Bamboo Plugin -This repository contains source code of Allure plugin for [Atlassian Bamboo CI](https://www.atlassian.com/software/bamboo). It allows you to generate Allure report from [existing Allure XML files](https://github.com/allure-framework/allure-core/wiki#gathering-information-about-tests). +This repository contains source code of Allure plugin +for [Atlassian Bamboo CI](https://www.atlassian.com/software/bamboo). It allows you to generate Allure report +from [existing Allure XML files](https://github.com/allure-framework/allure-core/wiki#gathering-information-about-tests). ### Building and Installing + #### Short way -Download precompiled JAR from [releases page](https://github.com/allure-framework/allure-bamboo-plugin/releases) and install it manually as described [here](https://confluence.atlassian.com/display/UPM/Installing+add-ons#Installingadd-ons-Installingbyfileupload). We use JDK 1.7+ to compile the plugin so be sure to use Java 1.7+ for running Bamboo. + +Download precompiled JAR from [releases page](https://github.com/allure-framework/allure-bamboo-plugin/releases) and +install it manually as +described [here](https://confluence.atlassian.com/display/UPM/Installing+add-ons#Installingadd-ons-Installingbyfileupload). +We use JDK 1.7+ to compile the plugin so be sure to use Java 1.7+ for running Bamboo. + #### Long way -1. Set up Atlassian plugin SDK as described [here](https://developer.atlassian.com/display/DOCS/Set+up+the+Atlassian+Plugin+SDK+and+Build+a+Project). + +1. Set up Atlassian plugin SDK as +described [here](https://developer.atlassian.com/display/DOCS/Set+up+the+Atlassian+Plugin+SDK+and+Build+a+Project). 2. Clone this repository 3. Run `$ atlas-run` 4. Access http://localhost:6990/bamboo/ to view development instance of Bamboo 5. Verify that plugin is working as expected -6. Install **target/allure-bamboo-plugin-VERSION.jar** manually as described [here](https://confluence.atlassian.com/display/UPM/Installing+add-ons#Installingadd-ons-Installingbyfileupload). +6. Install **target/allure-bamboo-plugin-VERSION.jar** manually as +described [here](https://confluence.atlassian.com/display/UPM/Installing+add-ons#Installingadd-ons-Installingbyfileupload). ### Configuration and Usage + Please follow the guide on the official Allure docs: https://docs.qameta.io/allure/#_bamboo diff --git a/pom.xml b/pom.xml index 84d0a15..4b69b50 100644 --- a/pom.xml +++ b/pom.xml @@ -51,7 +51,6 @@ com.fasterxml.jackson.dataformat jackson-dataformat-yaml 2.14.2 - provided com.fasterxml.jackson.core @@ -236,6 +235,7 @@ ${spotless.version} UTF-8 + UNIX @@ -265,7 +265,7 @@ - ,jakarta,javax,java,\# + ,jakarta,javax,java,\# .mvn/quality-configs/spotless/allure.java.license @@ -383,7 +383,9 @@ true - https://dcapt-downloads.s3.amazonaws.com/atlassian-security-scanner-dc-apps-suppressions.xml + + https://dcapt-downloads.s3.amazonaws.com/atlassian-security-scanner-dc-apps-suppressions.xml + diff --git a/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java b/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java index d1a2cb3..3ec29b5 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureArtifactsManager.java @@ -147,7 +147,7 @@ Optional getArtifactUrl(final String planKeyString, .flatMap(rs -> getArtifactHandlerByClassName( fromCustomData(rs.getCustomBuildData()).getArtifactHandlerClass()) .map(handler -> getArtifactUrl(planKeyString, buildNumber, - filePath, artifactConfig, planResultKey, handler) + filePath, artifactConfig, planResultKey, handler) ) ); } @@ -164,10 +164,10 @@ private String getArtifactUrl(final String planKeyString, final ArtifactDefinitionContextImpl artifactDef = getAllureArtifactDef(); return Optional.ofNullable( - artifactHandler.getArtifactLinkDataProvider( - mutableArtifact(planResultKey, artifactDef.getName()), - configProvider(artifactConfig) - )) + artifactHandler.getArtifactLinkDataProvider( + mutableArtifact(planResultKey, artifactDef.getName()), + configProvider(artifactConfig) + )) .map(lp -> getArtifactUrl(filePath, planResultKey, artifactDef, lp)) .orElse(null); } @@ -326,19 +326,19 @@ Optional uploadReportArtifacts(final @NotNull ImmutableChain final String errorMessage = "Unable to publish artifact via " + artifactHandler; final ArtifactHandlerPublishingResult publishingResult = BambooPluginUtils.callUnsafeCode( new BambooPluginUtils.NoThrowCallable(errorMessage) { - @NotNull - @Override - public ArtifactHandlerPublishingResult call() { - try { - return artifactHandler.publish( - summary.getPlanResultKey(), artifact, artifactPublishingConfig); - } catch (final Exception e) { - LOGGER.error("Failed to publish Allure Report using handler " - + artifactHandler.getClass().getName(), e); - return ArtifactHandlerPublishingResultImpl.failure(); - } - } - }); + @NotNull + @Override + public ArtifactHandlerPublishingResult call() { + try { + return artifactHandler.publish( + summary.getPlanResultKey(), artifact, artifactPublishingConfig); + } catch (final Exception e) { + LOGGER.error("Failed to publish Allure Report using handler " + + artifactHandler.getClass().getName(), e); + return ArtifactHandlerPublishingResultImpl.failure(); + } + } + }); if (publishingResult != null) { publishingResult.setArtifactHandlerKey(artifactHandler.getModuleDescriptor().getCompleteKey()); return Optional.of(allureBuildResult(publishingResult.isSuccessful(), null) @@ -451,17 +451,17 @@ private Optional getArtifactHandlerByClassName(fi final AtomicReference>> predicate = new AtomicReference<>(); return Optional.ofNullable(className) .map(clazz -> { - final Class aClass; - try { - aClass = (Class) Class.forName(clazz); - predicate.set(new ModuleOfClassPredicate<>(aClass).and(new EnabledModulePredicate())); - - return pluginAccessor.getModules(predicate.get()).stream().findAny().orElse(null); - } catch (ClassNotFoundException e) { - LOGGER.error("Failed to find artifact handler for class name " + className, e); + final Class aClass; + try { + aClass = (Class) Class.forName(clazz); + predicate.set(new ModuleOfClassPredicate<>(aClass).and(new EnabledModulePredicate())); + + return pluginAccessor.getModules(predicate.get()).stream().findAny().orElse(null); + } catch (ClassNotFoundException e) { + LOGGER.error("Failed to find artifact handler for class name " + className, e); + } + return null; } - return null; - } ); } } diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java index 20f61a6..5ef2a1d 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildCompleteAction.java @@ -126,7 +126,7 @@ public void execute(final @NotNull ImmutableChain chain, .orElseThrow(() -> new RuntimeException("Failed to find Allure executable by name " + executable)); // Creating a copy for customize report - AllureExecutable allureTmp = allure.getCopy(); + final AllureExecutable allureTmp = allure.getCopy(); LOGGER.info("Starting artifacts downloading into {} for {}", artifactsTempDir.getPath(), chain.getName()); final Collection artifactsPaths = artifactsManager.downloadAllArtifactsTo( diff --git a/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java b/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java index 41c8392..8035cdb 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureBuildConfig.java @@ -16,7 +16,6 @@ package io.qameta.allure.bamboo; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.validator.routines.UrlValidator; import javax.annotation.Nullable; import java.io.Serializable; diff --git a/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java b/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java index 4f5a8a7..9b9d353 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureDownloader.java @@ -79,8 +79,8 @@ private Optional downloadAllure(final String version) { return Downloader.download(url, downloadToFile); } catch (Exception e) { LOGGER - .warn("Failed to download from {}. Root cause : {}.", - url, e.toString()); + .warn("Failed to download from {}. Root cause : {}.", + url, e.toString()); } } } catch (Exception e) { @@ -91,11 +91,11 @@ private Optional downloadAllure(final String version) { private URL[] buildAllureDownloadUrls(final String version) throws MalformedURLException { final URL gitUrl = fromPath(settingsManager.getSettings().getDownloadBaseUrl()) - .path(String.format("%s/allure-%s.zip", version, version)) - .build().toURL(); + .path(String.format("%s/allure-%s.zip", version, version)) + .build().toURL(); final URL mavenUrl = fromPath(settingsManager.getSettings().getDownloadCliBaseUrl()) - .path(String.format("allure-commandline/%s/allure-commandline-%s.zip", version, version)) - .build().toURL(); + .path(String.format("allure-commandline/%s/allure-commandline-%s.zip", version, version)) + .build().toURL(); return new URL[]{gitUrl, mavenUrl}; } } diff --git a/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java b/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java index b9ce84e..c2e38d8 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureExecutable.java @@ -25,7 +25,6 @@ import javax.annotation.Nonnull; import java.io.File; import java.io.IOException; -import java.net.URL; import java.nio.file.Path; import java.util.Collection; import java.util.LinkedList; @@ -89,23 +88,27 @@ public void setCustomLogo(final String logoUrl) { } //Setting new Logo FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), - Pattern.compile("url\\('.+'\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + Pattern.compile("url\\('.+'\\)", + Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), "url(" + logoUrl + ")" ); // aligning logo to center FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), - Pattern.compile("(?<=\\s )left", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + Pattern.compile("(?<=\\s )left", + Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), "center" ); // fit logo to area FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), - Pattern.compile("(?<=\\s )!important;", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + Pattern.compile("(?<=\\s )!important;", + Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), "!important; background-size: contain !important;" ); // removing margin FileStringReplacer.replaceInFile(logoPluginFolder.resolve(cssFileName), - Pattern.compile("10px", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), + Pattern.compile("10px", + Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.COMMENTS), "0px" ); @@ -116,11 +119,11 @@ public void setCustomLogo(final String logoUrl) { } public AllureExecutable getCopy() throws IOException { - String binary = this.cmdPath.getFileName().toString(); - String binFolder = this.cmdPath.getParent().getFileName().toString(); - Path rootPath = this.cmdPath.getParent().getParent(); - Path rootFolderName = rootPath.getFileName(); - Path copyPath = createTempDirectory(rootFolderName.toString()); + final String binary = this.cmdPath.getFileName().toString(); + final String binFolder = this.cmdPath.getParent().getFileName().toString(); + final Path rootPath = this.cmdPath.getParent().getParent(); + final Path rootFolderName = rootPath.getFileName(); + final Path copyPath = createTempDirectory(rootFolderName.toString()); copyDirectoryToDirectory(rootPath.toFile(), copyPath.toFile()); return new AllureExecutable(copyPath diff --git a/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java b/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java index 730b236..88d7a3c 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureExecutableProvider.java @@ -70,7 +70,7 @@ Optional provide(final boolean isDownloadEnabled, final String } else if (isDownloadEnabled) { final Matcher nameMatcher = EXEC_NAME_PATTERN.matcher(executableName); return allureDownloader.downloadAndExtractAllureTo(allureHomeSubDir, - nameMatcher.matches() ? nameMatcher.group(1) : DEFAULT_VERSION) + nameMatcher.matches() ? nameMatcher.group(1) : DEFAULT_VERSION) .map(path -> executable).orElse(null); } return null; diff --git a/src/main/java/io/qameta/allure/bamboo/AllureReportServlet.java b/src/main/java/io/qameta/allure/bamboo/AllureReportServlet.java index f3a2f9d..cfa0a2b 100644 --- a/src/main/java/io/qameta/allure/bamboo/AllureReportServlet.java +++ b/src/main/java/io/qameta/allure/bamboo/AllureReportServlet.java @@ -100,7 +100,7 @@ private void setResponseHeaders(final HttpServletResponse response, final URI file = new URL(fileUrl).toURI(); final String mimeType = Optional.ofNullable(getServletContext().getMimeType(fileUrl)) .orElse(Files.probeContentType(Paths.get(file.getPath())) - ); + ); final String charsetPostfix = Stream.of("application", "text") .anyMatch(mimeType::contains) ? ";charset=utf-8" : ""; response.setHeader(CONTENT_TYPE, mimeType + charsetPostfix); @@ -152,7 +152,7 @@ private void uploadResultWasNotSuccess(final HttpServletResponse response, final String errorMessage = isEmpty(uploadResult.getFailureDetails()) ? "Unknown error has occurred during Allure Build. Please refer the server logs for details." : "Something went wrong with Allure Report generation. Here are some details: \n" - + uploadResult.getFailureDetails(); + + uploadResult.getFailureDetails(); try { response.setHeader(CONTENT_TYPE, "text/plain"); response.setHeader("Content-Length", String.valueOf(errorMessage.length())); diff --git a/src/main/java/io/qameta/allure/bamboo/BambooExecutablesManager.java b/src/main/java/io/qameta/allure/bamboo/BambooExecutablesManager.java index 0fd3a53..74b18ac 100644 --- a/src/main/java/io/qameta/allure/bamboo/BambooExecutablesManager.java +++ b/src/main/java/io/qameta/allure/bamboo/BambooExecutablesManager.java @@ -84,7 +84,7 @@ void addDefaultAllureExecutableCapability() { final CapabilityImpl capability = new CapabilityImpl(key, DEFAULT_PATH); capSet.addCapability(capability); capabilitySetManager.saveCapabilitySet(capSet); - }); + }); } @NotNull diff --git a/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Statistic.java b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Statistic.java index 3f93f90..af7a232 100644 --- a/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Statistic.java +++ b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Statistic.java @@ -43,7 +43,6 @@ public class Statistic extends AbstractSummary { /** * No args constructor for use in serialization. - * */ public Statistic() { // empty diff --git a/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Summary.java b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Summary.java index f7a52de..81bc87c 100644 --- a/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Summary.java +++ b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Summary.java @@ -45,10 +45,10 @@ public Summary() { } /** - * @param statistic statistic + * @param statistic statistic * @param reportName report name - * @param time time - * @param testRuns test runs + * @param time time + * @param testRuns test runs */ public Summary(final String reportName, final List testRuns, diff --git a/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Time.java b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Time.java index 85b63f1..1f01673 100644 --- a/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Time.java +++ b/src/main/java/io/qameta/allure/bamboo/info/allurewidgets/summary/Time.java @@ -49,11 +49,11 @@ public Time() { } /** - * @param duration duration + * @param duration duration * @param sumDuration sum of duration * @param minDuration min duration - * @param stop stop time - * @param start start time + * @param stop stop time + * @param start start time * @param maxDuration max duration */ public Time(final Long start, diff --git a/src/main/java/io/qameta/allure/bamboo/util/Downloader.java b/src/main/java/io/qameta/allure/bamboo/util/Downloader.java index 45b54a0..5132f5d 100644 --- a/src/main/java/io/qameta/allure/bamboo/util/Downloader.java +++ b/src/main/java/io/qameta/allure/bamboo/util/Downloader.java @@ -41,16 +41,16 @@ private Downloader() { public static Optional download(final URL url, final Path target) throws IOException { - final URLConnection connection = url.openConnection(); - connection.setConnectTimeout(CONN_TIMEOUT_MS); - connection.setReadTimeout(DOWNLOAD_TIMEOUT_MS); - connection.setRequestProperty("Connection", "close"); - connection.setRequestProperty("Pragma", "no-cache"); - ((HttpURLConnection) connection).setInstanceFollowRedirects(true); - connection.connect(); - try (InputStream input = connection.getInputStream()) { - Files.copy(input, target, StandardCopyOption.REPLACE_EXISTING); - return Optional.of(target); - } + final URLConnection connection = url.openConnection(); + connection.setConnectTimeout(CONN_TIMEOUT_MS); + connection.setReadTimeout(DOWNLOAD_TIMEOUT_MS); + connection.setRequestProperty("Connection", "close"); + connection.setRequestProperty("Pragma", "no-cache"); + ((HttpURLConnection) connection).setInstanceFollowRedirects(true); + connection.connect(); + try (InputStream input = connection.getInputStream()) { + Files.copy(input, target, StandardCopyOption.REPLACE_EXISTING); + return Optional.of(target); + } } } diff --git a/src/main/resources/allure-bamboo.properties b/src/main/resources/allure-bamboo.properties index 9764fb4..8382a79 100644 --- a/src/main/resources/allure-bamboo.properties +++ b/src/main/resources/allure-bamboo.properties @@ -1,32 +1,28 @@ -allureplugin.policy = Generate Report -allureplugin.policy.description = Choose condition when report should be built -allureplugin.policy.error = Select for which builds to generate report -allureplugin.policy.all = For all builds -allureplugin.policy.with_problems = For builds with problems -allureplugin.policy.failed = For failed builds - -allure.result.directory.label = Allure result directory -allure.result.directory.description = Specify the directory with allure results relative from build directory. \ +allureplugin.policy=Generate Report +allureplugin.policy.description=Choose condition when report should be built +allureplugin.policy.error=Select for which builds to generate report +allureplugin.policy.all=For all builds +allureplugin.policy.with_problems=For builds with problems +allureplugin.policy.failed=For failed builds +allure.result.directory.label=Allure result directory +allure.result.directory.description=Specify the directory with allure results relative from build directory. \ An example allure-results/ -allure.report.path.prefix.label = Report artifact subdirectory -allure.report.path.prefix.description = The subdirectory (or subdirectories) to put generated report into. \ +allure.report.path.prefix.label=Report artifact subdirectory +allure.report.path.prefix.description=The subdirectory (or subdirectories) to put generated report into. \ An example allure-report/ -allure.issues.tracker.pattern.label = Issue tracker pattern -allure.issues.tracker.pattern.description = \ +allure.issues.tracker.pattern.label=Issue tracker pattern +allure.issues.tracker.pattern.description=\ Specify the issue tracker pattern. E.g. http://bugtracker.yourcompany.com/issues/%s \ For more information you can see this wiki page. -allure.tests.management.pattern.label = Test management pattern -allure.tests.management.pattern.description = \ +allure.tests.management.pattern.label=Test management pattern +allure.tests.management.pattern.description=\ Specify the test management system pattern. E.g. http://tms.yourcompany.com/tests/%s \ For more information you can see this wiki page. - -allure.task.help.link = https://docs.qameta.io/allure/latest/#_bamboo -allure.task.help.title = Go to Allure website! - -error.property.empty = The property value should not be empty -error.path.absolute = The path should be relative -error.address.placeholder = The pattern should contain exactly one placeholder <%s> - +allure.task.help.link=https://docs.qameta.io/allure/latest/#_bamboo +allure.task.help.title=Go to Allure website! +error.property.empty=The property value should not be empty +error.path.absolute=The path should be relative +error.address.placeholder=The pattern should contain exactly one placeholder <%s> webitems.system.admin.build.allureReport=Allure Report admin.allureReportConfig.edit.title=Configure Allure Reporting admin.allureReportConfig.description= @@ -44,6 +40,5 @@ allure.config.local.storage.label=Allure local storage allure.config.local.storage.label.required=Allure local storage is required build.allure.title=Allure Report buildResult.allure.title=Allure Report - allure.config.logo.enabled.label=Enable report custom logo custom.allure.logo.url.label=Custom logo diff --git a/src/main/resources/templates/editAllureReportConfig.ftl b/src/main/resources/templates/editAllureReportConfig.ftl index f93e505..8b9ff1a 100644 --- a/src/main/resources/templates/editAllureReportConfig.ftl +++ b/src/main/resources/templates/editAllureReportConfig.ftl @@ -3,30 +3,30 @@ - [@ww.text name='allure.plugin.title' /] + [@ww.text name='allure.plugin.title' /] -

[@ww.text name='allure.plugin.title' /]

+

[@ww.text name='allure.plugin.title' /]

-

[@ww.text name='admin.allureReportConfig.description' /]

+

[@ww.text name='admin.allureReportConfig.description' /]

- [@ww.form action="saveAllureReportConfig" - id="saveAllureReportConfigForm" - submitLabelKey='global.buttons.update' - titleKey='admin.allureReportConfig.edit.title' - cancelUri='/admin/editAllureReportConfig.action' - ] - [@ww.checkbox labelKey='allure.config.download.enabled.label' name='custom.allure.config.download.enabled' toggle='true' /] +[@ww.form action="saveAllureReportConfig" +id="saveAllureReportConfigForm" +submitLabelKey='global.buttons.update' +titleKey='admin.allureReportConfig.edit.title' +cancelUri='/admin/editAllureReportConfig.action' +] + [@ww.checkbox labelKey='allure.config.download.enabled.label' name='custom.allure.config.download.enabled' toggle='true' /] - [@ww.checkbox labelKey='allure.config.logo.enabled.label' name='custom.allure.config.logo.enabled' toggle='true' /] + [@ww.checkbox labelKey='allure.config.logo.enabled.label' name='custom.allure.config.logo.enabled' toggle='true' /] - [@ww.checkbox labelKey='allure.config.enabled.default.label' name='custom.allure.config.enabled.default' toggle='true' /] + [@ww.checkbox labelKey='allure.config.enabled.default.label' name='custom.allure.config.enabled.default' toggle='true' /] - [@ww.textfield labelKey="allure.config.download.url.label" name="custom.allure.config.download.url" required="true"/] + [@ww.textfield labelKey="allure.config.download.url.label" name="custom.allure.config.download.url" required="true"/] - [@ww.textfield labelKey="allure.config.local.storage.label" name="custom.allure.config.local.storage" required="true"/] - [/@ww.form] + [@ww.textfield labelKey="allure.config.local.storage.label" name="custom.allure.config.local.storage" required="true"/] +[/@ww.form] - \ No newline at end of file + diff --git a/src/main/resources/templates/error.ftl b/src/main/resources/templates/error.ftl index bf3bb18..198de7d 100644 --- a/src/main/resources/templates/error.ftl +++ b/src/main/resources/templates/error.ftl @@ -3,19 +3,19 @@ - [@ww.text name='error.title' /] + [@ww.text name='error.title' /] - [@ui.header pageKey='error.heading' /] +[@ui.header pageKey='error.heading' /] - [#if formattedActionErrors?has_content] - [@ui.messageBox type='warning'] - [#list formattedActionErrors as error] -

${error}

- [/#list] - [/@ui.messageBox] - [/#if] +[#if formattedActionErrors?has_content] + [@ui.messageBox type='warning'] + [#list formattedActionErrors as error] +

${error}

+ [/#list] + [/@ui.messageBox] +[/#if] - \ No newline at end of file + diff --git a/src/main/resources/templates/viewAllureReport.ftl b/src/main/resources/templates/viewAllureReport.ftl index 281b6ea..3ee3500 100644 --- a/src/main/resources/templates/viewAllureReport.ftl +++ b/src/main/resources/templates/viewAllureReport.ftl @@ -1,19 +1,19 @@ [#-- @ftlvariable name="" type="io.qameta.allure.bamboo.ViewAllureReport" --] -[#assign reportUrl = "${baseUrl}/plugins/servlet/allure/report/${planKey}/${buildNumber}/"] -[#assign reportZipUrl = "${baseUrl}/plugins/servlet/allure/report/${planKey}/${buildNumber}/report.zip"] -[@ui.header pageKey='buildResult.changes.title' object='${immutablePlan.name} ${resultsSummary.buildNumber}' title=true/] + [#assign reportUrl = "${baseUrl}/plugins/servlet/allure/report/${planKey}/${buildNumber}/"] + [#assign reportZipUrl = "${baseUrl}/plugins/servlet/allure/report/${planKey}/${buildNumber}/report.zip"] + [@ui.header pageKey='buildResult.changes.title' object='${immutablePlan.name} ${resultsSummary.buildNumber}' title=true/]