Imagine a bacon-wrapped Ferrari. Still not better than our free technical reports.
See all our reports

Jenkins Protip – Artifact Propagation

Jenkins is a continuous integration tool that is very often used as a orchestration tool for continuous deployment and delivery. Today, we will look how to do artifact propagation in a Jenkins pipeline for Continuous Delivery. Some of questions I’m thinking about are:

  • How to make sure that different jobs in the pipeline use the same artifacts?
  • How will these jobs get hold of those artifacts in a distributed environment?
  • How can we make sure that 3rd party services also have access to those artifacts?
  • There are multiple ways how to support this and in this article we will take a look at two of these. For seeing how to chain jobs together then please refer to How to use Jenkins for Job Chaining and Visualizations.

    Copy Artifact Plugin

    Of course there is a plugin for that! One of the best things about Jenkins is that it has a massive library of plugins (I wrote a popular post on my Top 10 Must-have Jenkins features/plugins if you want to see more).

    Check out the Copy Artifact Plugin. The core concept of the plugin is that your Jenkins job needs to archive artifacts. Basically this means that if you produce a JAR/WAR/EAR or some other artifact then you instruct Jenkins to save it for later use. Once your jobs are doing that you can tell other jobs to start using those artifacts.

    Archiving is nothing more than specifying a Post-build Action in the job configuration. Specify artifact to archive or use a wildcard to archive more than one. In this screenshot we are archiving the WAR archive from target/lr-demo.war.

    In the following screenshot I have configured a job to use this artifact. I’ve outlined in the Pre Steps section that I will be using an artifact from another job build-chat and the artifact is target/lr-demo.war and it will get copied to copied-tmp. It will keep the folder structure of the source and the file will end up as copied-tmp/target/lr-demo.war. There is an option to override that.

    Your Favourite Artifact Repository

    Although the Copy Artifact is a quick and easy way to distribute your archive from one job to another, at one point you want your company artifact repository to know about these builds. We for example at ZeroTurnaround treat Jenkins cluster as a – the cluster might blow up any second and we’ll re-provision. We hold our artifacts in Nexus (we are considering Artifactory also). This means we want our artifacts, snapshots and releases to end up in that central repository instead.

    One quick way to get them there is to use the mvn deploy-file. This does not require you to even have your project set up as a maven project. For example the following line deploys your artifact with the Jenkins BUILD_NUMBER embedded into the name to your repository.

    mvn deploy:deploy-file -Durl=http://your-repo -DrepositoryId=your-repo-id\
         -Dfile=filename.jar \
         -DgroupId=groupId \
         -DartifactId=artifactId\
         -Dversion=ver-${BUILD_NUMBER}-SNAPSHOT \
         -Dpackaging=jar

    Next step is to use this very same artifact in your other jobs. There you can use the mvn dependency:get plugin. Before version 2.4 it was not so easy to download from the repository to a pre-defined location (you needed a pom.xml) but now you can execute the following command to download the artifact to the current folder.

    mvn org.apache.maven.plugins:maven-dependency-plugin:2.4:get \
        -DrepoUrl=repo-name::repo-id::http://your-repo \
        -Dartifact=gropuId:artifactId:ver-${BUILD_NUMBER}-SNAPSHOT -Ddest=zt-zip.jar

    Of course now is the question where will this other job know the ${BUILD_NUMBER}. Well, there are couple of options. If you have a pipeline, then be sure to use the proper trigger plugin (see How to use Jenkins for Job Chaining and Visualizations). Other option is to take the latest snapshot from the repository or parameterize your build that would require the build number.

    Conclusions

    Jenkins comes with a plugin that does the trick and works perfectly for most of the situation. It is called Copy Artifact plugin. It does require some setup. Your projects must archive artifacts and secondly your job needs to copy those artifacts as a pre step.

    The other option is to use your favourite artifact repository. Your Jenkins job will upload the artifact and optionally embed some more information there. The build number for example and then your other jobs can use an artifact from the repository. This also means that your other systems that anyways are using your artifact repository will always see the latest and greatest versions.

    If you know any other good ways for artifact propagation in Jenkins then do let us know!