package org.jfrog.bamboo.deployment; import com.atlassian.bamboo.build.logger.BuildLogger; import com.atlassian.bamboo.deployments.execution.DeploymentTaskContext; import com.atlassian.bamboo.deployments.execution.DeploymentTaskType; import com.atlassian.bamboo.task.TaskException; import com.atlassian.bamboo.task.TaskResult; import com.atlassian.bamboo.task.TaskResultBuilder; import com.atlassian.bamboo.task.runtime.RuntimeTaskDefinition; import com.google.common.collect.Sets; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.jetbrains.annotations.NotNull; import org.jfrog.bamboo.admin.ServerConfig; import org.jfrog.bamboo.admin.ServerConfigManager; import org.jfrog.bamboo.context.AbstractBuildContext; import org.jfrog.bamboo.util.BuildInfoLog; import org.jfrog.bamboo.util.TaskUtils; import org.jfrog.bamboo.util.deployment.FilesCollector; import org.jfrog.build.api.util.FileChecksumCalculator; import org.jfrog.build.client.DeployDetails; import org.jfrog.build.extractor.clientConfiguration.client.ArtifactoryBuildInfoClient; import java.io.File; import java.io.IOException; import java.util.Map; import java.util.Set; /** * Bamboo deployment Artifactory task - Takes pre defined artifacts from a build plan and deploys them to Artifactory * * @author Aviad Shikloshi */ public class ArtifactoryDeploymentTask implements DeploymentTaskType { private static final Logger log = Logger.getLogger(ArtifactoryDeploymentTask.class); private String repositoryKey; private String artifactsRootDirectory; private BuildLogger buildLogger; private ArtifactoryBuildInfoClient client; @NotNull @Override public TaskResult execute(@NotNull DeploymentTaskContext deploymentTaskContext) throws TaskException { buildLogger = deploymentTaskContext.getBuildLogger(); ServerConfigManager serverConfigManager = ServerConfigManager.getInstance(); String serverId = deploymentTaskContext.getConfigurationMap().get(ArtifactoryDeploymentConfiguration.DEPLOYMENT_PREFIX + AbstractBuildContext.SERVER_ID_PARAM); if (StringUtils.isBlank(serverId)) { // Compatibility with version 1.8.0 serverId = deploymentTaskContext.getConfigurationMap().get("artifactoryServerId"); } ServerConfig serverConfig = serverConfigManager.getServerConfigById(Long.parseLong(serverId)); if (serverConfig == null) { buildLogger.addErrorLogEntry("Could not find Artifactpry server. Please check the Artifactory server in the task configuration."); return TaskResultBuilder.newBuilder(deploymentTaskContext).failedWithError().build(); } repositoryKey = deploymentTaskContext.getConfigurationMap().get(ArtifactoryDeploymentConfiguration.DEPLOYMENT_PREFIX + ArtifactoryDeploymentConfiguration.DEPLOYMENT_REPOSITORY); if (StringUtils.isBlank(repositoryKey)) { // Compatibility with version 1.8.0 repositoryKey = deploymentTaskContext.getConfigurationMap().get(ArtifactoryDeploymentConfiguration.DEPLOYMENT_REPOSITORY); } artifactsRootDirectory = deploymentTaskContext.getRootDirectory().getAbsolutePath(); // Get the deployer credentials configured in the task configuration String username = deploymentTaskContext.getConfigurationMap().get(ArtifactoryDeploymentConfiguration.DEPLOYMENT_PREFIX + ArtifactoryDeploymentConfiguration.USERNAME); String password = deploymentTaskContext.getConfigurationMap().get(ArtifactoryDeploymentConfiguration.DEPLOYMENT_PREFIX + ArtifactoryDeploymentConfiguration.PASSWORD); // If deployer credentials were not configured in the task configuration, use the credentials configured // globally if (StringUtils.isBlank(username) && StringUtils.isBlank(password)) { username = serverConfig.getUsername(); password = serverConfig.getPassword(); } TaskResult result; client = new ArtifactoryBuildInfoClient(serverConfig.getUrl(), username, password, new BuildInfoLog(log)); try { RuntimeTaskDefinition artifactDownloadTask = TaskUtils.findDownloadArtifactsTask(deploymentTaskContext.getCommonContext().getRuntimeTaskDefinitions()); FilesCollector filesCollector = new FilesCollector(artifactsRootDirectory, artifactDownloadTask); Map<String, Set<File>> artifacts = filesCollector.getCollectedFiles(); Set<DeployDetails> deployDetailsSet = createDeploymentDetailsForArtifacts(artifacts); deploy(deployDetailsSet); result = TaskResultBuilder.newBuilder(deploymentTaskContext).success().build(); } catch (Exception e) { buildLogger.addErrorLogEntry("Error while deploying artifacts to Artifactory: " + e.getMessage()); result = TaskResultBuilder.newBuilder(deploymentTaskContext).failedWithError().build(); } finally { client.close(); } return result; } /** * Deploy all collected artifacts to Artifactory * * @param deployDetailsSet details for the artifacts we want to deploy * @throws IOException */ private void deploy(Set<DeployDetails> deployDetailsSet) throws IOException { for (DeployDetails deployDetails : deployDetailsSet) { buildLogger.addBuildLogEntry("Deploying: " + deployDetails.getArtifactPath() + " to: " + deployDetails.getTargetRepository()); client.deployArtifact(deployDetails); } } /** * Create DeployDetails for all the collected artifacts * * @param artifacts files to be uploaded to Artifactory * @return set of all deployment details */ private Set<DeployDetails> createDeploymentDetailsForArtifacts(Map<String, Set<File>> artifacts) { Set<DeployDetails> deployDetailList = Sets.newHashSet(); for (String path : artifacts.keySet()) { Set<File> filesForPath = artifacts.get(path); for (File file : filesForPath) { deployDetailList.add(createDeployDetailsForOneArtifact(file, path)); } } return deployDetailList; } /** * Create DeploymentDetails for artifact * * @param artifact artifact file object * @return DeploymentDetails for artifact */ private DeployDetails createDeployDetailsForOneArtifact(File artifact, String pathToArtifact) { DeployDetails.Builder deployDetailsBuilder = new DeployDetails.Builder(); try { Map<String, String> checksum = FileChecksumCalculator.calculateChecksums(artifact, "SHA1", "MD5"); deployDetailsBuilder .artifactPath(createArtifactPath(artifact.getPath(), pathToArtifact)) .file(artifact) .targetRepository(repositoryKey) .sha1(checksum.get("SHA1")) .md5(checksum.get("MD5")); return deployDetailsBuilder.build(); } catch (Exception e) { throw new RuntimeException("Error while creating Artifact details. " + e.getMessage(), e); } } /** * Create the artifact path in artifactory * * @param artifactPath full artifact path on file system * @return the calculated path to deploy to inside the repository */ private String createArtifactPath(String artifactPath, String subDir) { int numberOfSeparators = StringUtils.isBlank(subDir) ? 1 : 2; int start = artifactsRootDirectory.length() + subDir.length() + numberOfSeparators; return StringUtils.substring(artifactPath, start).replace("\\", "/"); } }