package org.jfrog.hudson.util; import hudson.matrix.Combination; import hudson.matrix.MatrixRun; import hudson.model.*; import org.jfrog.hudson.ArtifactoryRedeployPublisher; import org.jfrog.hudson.BuildInfoAwareConfigurator; import org.jfrog.hudson.action.ActionableHelper; import org.jfrog.hudson.gradle.ArtifactoryGradleConfigurator; import java.util.logging.Logger; /** * Utility class to help extracting and assembling parameters for the a unique build identifier. * * @author Tomer Cohen */ public class BuildUniqueIdentifierHelper { private static Logger debuggingLogger = Logger.getLogger(BuildUniqueIdentifierHelper.class.getName()); private BuildUniqueIdentifierHelper() { // utility class throw new IllegalAccessError(); } /** * Get the root build which triggered the current build. The build root is considered to be the one furthest one * away from the current build which has the isPassIdentifiedDownstream active, if no parent build exists, check * that the current build needs an upstream identifier, if it does return it. * * @param currentBuild The current build. * @return The root build with isPassIdentifiedDownstream active. Null if no upstream or non is found. */ public static AbstractBuild<?, ?> getRootBuild(AbstractBuild<?, ?> currentBuild) { AbstractBuild<?, ?> rootBuild = null; AbstractBuild<?, ?> parentBuild = getUpstreamBuild(currentBuild); while (parentBuild != null) { if (isPassIdentifiedDownstream(parentBuild)) { rootBuild = parentBuild; } parentBuild = getUpstreamBuild(parentBuild); } if (rootBuild == null && isPassIdentifiedDownstream(currentBuild)) { return currentBuild; } return rootBuild; } private static AbstractBuild<?, ?> getUpstreamBuild(AbstractBuild<?, ?> build) { AbstractBuild<?, ?> upstreamBuild; Cause.UpstreamCause cause = ActionableHelper.getUpstreamCause(build); if (cause == null) { return null; } AbstractProject<?, ?> upstreamProject = getProject(cause.getUpstreamProject()); if (upstreamProject == null) { debuggingLogger.fine("No project found answering for the name: " + cause.getUpstreamProject()); return null; } upstreamBuild = upstreamProject.getBuildByNumber(cause.getUpstreamBuild()); if (upstreamBuild == null) { debuggingLogger.fine( "No build with name: " + upstreamProject.getName() + " and number: " + cause.getUpstreamBuild()); } return upstreamBuild; } /** * Get a project according to its full name. * * @param fullName The full name of the project. * @return The project which answers the full name. */ private static AbstractProject<?, ?> getProject(String fullName) { Item item = Hudson.getInstance().getItemByFullName(fullName); if (item != null && item instanceof AbstractProject) { return (AbstractProject<?, ?>) item; } return null; } /** * Check whether to pass the the downstream identifier according to the <b>root</b> build's descriptor * * @param build The current build * @return True if to pass the downstream identifier to the child projects. */ public static boolean isPassIdentifiedDownstream(AbstractBuild<?, ?> build) { ArtifactoryRedeployPublisher publisher = ActionableHelper.getPublisher(build.getProject(), ArtifactoryRedeployPublisher.class); if (publisher != null) { return publisher.isPassIdentifiedDownstream(); } ArtifactoryGradleConfigurator wrapper = ActionableHelper .getBuildWrapper((BuildableItemWithBuildWrappers) build.getProject(), ArtifactoryGradleConfigurator.class); return wrapper != null && wrapper.isPassIdentifiedDownstream(); } /** * Get the identifier from the <b>root</b> build. which is composed of {@link hudson.model.AbstractProject#getFullName()} * -{@link hudson.model.Run#getNumber()} * * @param rootBuild The root build * @return The upstream identifier. */ public static String getUpstreamIdentifier(AbstractBuild<?, ?> rootBuild) { if (rootBuild != null) { AbstractProject<?, ?> rootProject = rootBuild.getProject(); return ExtractorUtils.sanitizeBuildName(rootProject.getFullName()) + "-" + rootBuild.getNumber(); } return null; } public static String getBuildName(Run build) { String lastItemInBuildName = build.getParent().getName(); String buildName = build.getParent().getFullName(); if (!buildName.equals(lastItemInBuildName)) { if (build instanceof MatrixRun) { // If we are using Multi-configuration plugin we want to omit the parameters in the end of the build name int stringToBeOmittedIndex = buildName.indexOf(lastItemInBuildName); if (stringToBeOmittedIndex > 0) { buildName = buildName.substring(0, stringToBeOmittedIndex - 1); } } } return ExtractorUtils.sanitizeBuildName(buildName); } public static String getBuildNumber(Run build) { String buildNumber = String.valueOf(build.getNumber()); if (build instanceof MatrixRun) { buildNumber += " :: "; Combination combination = ((MatrixRun) build).getProject().getCombination(); buildNumber += combination.toString(); } return buildNumber; } public static String getBuildNameConsiderOverride(BuildInfoAwareConfigurator configurator, Run build) { return configurator.isOverrideBuildName() ? configurator.getCustomBuildName() : BuildUniqueIdentifierHelper.getBuildName(build); } }