All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jfrog.hudson.generic.GenericArtifactsDeployer Maven / Gradle / Ivy

The newest version!
package org.jfrog.hudson.generic;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import hudson.EnvVars;
import hudson.FilePath;
import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.Cause;
import hudson.model.Hudson;
import hudson.remoting.VirtualChannel;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.jfrog.build.api.Artifact;
import org.jfrog.build.api.BuildInfoFields;
import org.jfrog.build.api.builder.ArtifactBuilder;
import org.jfrog.build.api.util.FileChecksumCalculator;
import org.jfrog.build.client.ArtifactoryBuildInfoClient;
import org.jfrog.build.client.DeployDetails;
import org.jfrog.build.client.ProxyConfiguration;
import org.jfrog.build.util.PublishedItemsHelper;
import org.jfrog.hudson.ArtifactoryServer;
import org.jfrog.hudson.action.ActionableHelper;
import org.jfrog.hudson.util.Credentials;
import org.jfrog.hudson.util.ExtractorUtils;

import java.io.File;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Deploys artifacts to Artifactory. This class is used only in free style generic configurator.
 *
 * @author Shay Yaakov
 */
public class GenericArtifactsDeployer {
    private static final String SHA1 = "SHA1";
    private static final String MD5 = "MD5";

    private AbstractBuild build;
    private ArtifactoryGenericConfigurator configurator;
    private BuildListener listener;
    private Credentials credentials;
    private EnvVars env;
    private List artifactsToDeploy = Lists.newArrayList();

    public GenericArtifactsDeployer(AbstractBuild build, ArtifactoryGenericConfigurator configurator,
            BuildListener listener, Credentials credentials)
            throws IOException, InterruptedException, NoSuchAlgorithmException {
        this.build = build;
        this.configurator = configurator;
        this.listener = listener;
        this.credentials = credentials;
        this.env = build.getEnvironment(listener);
    }

    public List getDeployedArtifacts() {
        return artifactsToDeploy;
    }

    public void deploy()
            throws IOException, InterruptedException {
        final Multimap result = HashMultimap.create();
        String deployPattern = Util.replaceMacro(configurator.getDeployPattern(), env);
        deployPattern = StringUtils.replace(deployPattern, "\r\n", "\n");
        deployPattern = StringUtils.replace(deployPattern, ",", "\n");
        Multimap pairs = PublishedItemsHelper.getPublishedItemsPatternPairs(deployPattern);
        if (pairs.isEmpty()) {
            return;
        }

        FilePath workingDir = build.getWorkspace();
        Map propertiesToAdd = getbuildPropertiesMap();
        ArtifactoryServer artifactoryServer = configurator.getArtifactoryServer();
        artifactsToDeploy = workingDir.act(new FilesDeployerCallable(listener, pairs, artifactoryServer, credentials,
                configurator.getRepositoryKey(), propertiesToAdd,
                artifactoryServer.createProxyConfiguration(Hudson.getInstance().proxy)));
    }

    private Map getbuildPropertiesMap() {
        Map properties = Maps.newHashMap();

        properties.put("build.name", ExtractorUtils.sanitizeBuildName(build.getParent().getFullName()));
        properties.put("build.number", build.getNumber() + "");
        properties.put("build.timestamp", build.getTimestamp().getTime().getTime() + "");
        Cause.UpstreamCause parent = ActionableHelper.getUpstreamCause(build);
        if (parent != null) {
            properties.put("build.parentName", ExtractorUtils.sanitizeBuildName(parent.getUpstreamProject()));
            properties.put("build.parentNumber", parent.getUpstreamBuild() + "");
        }
        String revision = ExtractorUtils.getVcsRevision(env);
        if (StringUtils.isNotBlank(revision)) {
            properties.put(BuildInfoFields.VCS_REVISION, revision);
        }

        addMatrixParams(properties);

        return properties;
    }

    private void addMatrixParams(Map properties) {
        String[] matrixParams = StringUtils.split(configurator.getMatrixParams(), "; ");
        if (matrixParams == null) {
            return;
        }
        for (String matrixParam : matrixParams) {
            String[] split = StringUtils.split(matrixParam, '=');
            if (split.length == 2) {
                String value = Util.replaceMacro(split[1], env);
                properties.put(split[0], value);
            }
        }
    }

    private static class FilesDeployerCallable implements FilePath.FileCallable> {

        private BuildListener listener;
        private Multimap patternPairs;
        private ArtifactoryServer server;
        private Credentials credentials;
        private final String repositoryKey;
        private Map buildProperties;
        private ProxyConfiguration proxyConfiguration;

        public FilesDeployerCallable(BuildListener listener, Multimap patternPairs,
                ArtifactoryServer server, Credentials credentials, String repositoryKey,
                Map buildProperties, ProxyConfiguration proxyConfiguration) {
            this.listener = listener;
            this.patternPairs = patternPairs;
            this.server = server;
            this.credentials = credentials;
            this.repositoryKey = repositoryKey;
            this.buildProperties = buildProperties;
            this.proxyConfiguration = proxyConfiguration;
        }

        public List invoke(File workspace, VirtualChannel channel) throws IOException, InterruptedException {
            Multimap targetPathToFilesMap = buildTargetPathToFiles(workspace);
            Set artifactsToDeploy = Sets.newHashSet();
            for (Map.Entry entry : targetPathToFilesMap.entries()) {
                artifactsToDeploy.addAll(buildDeployDetailsFromFileEntry(entry));
            }

            ArtifactoryBuildInfoClient client = server.createArtifactoryClient(credentials.getUsername(),
                    credentials.getPassword(), proxyConfiguration);
            try {
                deploy(client, artifactsToDeploy);
                return convertDeployDetailsToArtifacts(artifactsToDeploy);
            } finally {
                client.shutdown();
            }
        }

        private List convertDeployDetailsToArtifacts(Set details) {
            List result = Lists.newArrayList();
            for (DeployDetails detail : details) {
                String ext = FilenameUtils.getExtension(detail.getFile().getName());
                Artifact artifact = new ArtifactBuilder(detail.getFile().getName()).md5(detail.getMd5())
                        .sha1(detail.getSha1()).type(ext).build();
                result.add(artifact);
            }
            return result;
        }

        public void deploy(ArtifactoryBuildInfoClient client, Set artifactsToDeploy)
                throws IOException {
            for (DeployDetails deployDetail : artifactsToDeploy) {
                StringBuilder deploymentPathBuilder = new StringBuilder(server.getUrl());
                deploymentPathBuilder.append("/").append(repositoryKey);
                if (!deployDetail.getArtifactPath().startsWith("/")) {
                    deploymentPathBuilder.append("/");
                }
                deploymentPathBuilder.append(deployDetail.getArtifactPath());
                listener.getLogger().println("Deploying artifact: " + deploymentPathBuilder.toString());
                client.deployArtifact(deployDetail);
            }
        }

        private Multimap buildTargetPathToFiles(File workspace) throws IOException {
            Multimap result = HashMultimap.create();
            for (Map.Entry entry : patternPairs.entries()) {
                String pattern = entry.getKey();
                String targetPath = entry.getValue();
                Multimap publishingData = PublishedItemsHelper.buildPublishingData(workspace, pattern,
                        targetPath);
                if (publishingData != null) {
                    listener.getLogger().println(
                            "For pattern: " + pattern + " " + publishingData.size() + " artifacts were found");
                    result.putAll(publishingData);
                } else {
                    listener.getLogger().println("For pattern: " + pattern + " no artifacts were found");
                }
            }

            return result;
        }

        private Set buildDeployDetailsFromFileEntry(Map.Entry fileEntry)
                throws IOException {
            Set result = Sets.newHashSet();
            String targetPath = fileEntry.getKey();
            File artifactFile = fileEntry.getValue();
            String path = PublishedItemsHelper.calculateTargetPath(targetPath, artifactFile);
            path = StringUtils.replace(path, "//", "/");

            // calculate the sha1 checksum that is not given by Jenkins and add it to the deploy artifactsToDeploy
            Map checksums = Maps.newHashMap();
            try {
                checksums = FileChecksumCalculator.calculateChecksums(artifactFile, SHA1, MD5);
            } catch (NoSuchAlgorithmException e) {
                listener.getLogger().println("Could not find checksum algorithm for " + SHA1 + " or " + MD5);
            }
            DeployDetails.Builder builder = new DeployDetails.Builder()
                    .file(artifactFile)
                    .artifactPath(path)
                    .targetRepository(repositoryKey)
                    .md5(checksums.get(MD5)).sha1(checksums.get(SHA1))
                    .addProperties(buildProperties);
            result.add(builder.build());

            return result;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy