HomeAboutArchivesTools & ResourcesSupport me
Hi! 👋 I'm Szymon

I help you become a better software developer.

  • 1.15kFollowers
  • 2.36kSubscribers
  • 110Followers
  • 30.2kReputation

Latest posts from the Jenkins Pipeline Cookbook

Jenkins Declarative Pipeline with the dynamic agent - how to ...
5 Common Jenkins Pipeline Mistakes
How to catch curl response in Jenkins Pipeline?
How to time out Jenkins Pipeline stage and keep the pipeline ...
Jenkins Scripted Pipeline vs. Declarative Pipeline - the 4 pr...
Using Jenkins Pipeline parallel stages to build Maven project...
Building Java and Maven docker images using parallelized Jenk...
More

Popular categories

  • Groovy Cookbook28
  • Jenkins Pipeline Cookbook9
  • Programmer's Bookshelf6
  • Micronaut Cookbook4
  • Ratpack Cookbook4
  • Learning Java4
  • jq cookbook3
  • How to3
  • Blog Reports2

Don't miss anything - join my newsletter

Additional materials and updates for subscribers. No spam guaranteed.
Unsubscribe at any time.

Did you like this article?

Spread the !
  • ☕️
  1. e.printstacktrace.blog
  2. Jenkins Pipeline Cookbook

Using Jenkins Pipeline parallel stages to build Maven project with different JDKs

  • November 28, 2019
  • 3 min. read
  • 0 Comments

In one of the latest blog posts, I have shown you how you can build a Docker image with Java and Maven installed with the SDKMAN! command-line tool. Today I would like to continue the topic and show you, how you can compile your project using two different Java versions in parallel.

Using dockerfile agent

Sample Maven application used in this article can be found here - wololock/simple-java-maven-app.

To keep the example simple, I’m going to use Jenkins Pipeline’s dockerfile agent. It executes given pipeline stage (or stages) in a docker container that gets started from a docker image created using local Dockerfile.

Listing 1. Dockerfile.build (source)
FROM debian:stretch-slim

# Defining default Java and Maven version
ARG JAVA_VERSION="8.0.232-open"
ARG MAVEN_VERSION="3.6.3"

# Defining default non-root user UID, GID, and name
ARG USER_UID="1000"
ARG USER_GID="1000"
ARG USER_NAME="jenkins"

# Creating default non-user
RUN groupadd -g $USER_GID $USER_NAME && \
   useradd -m -g $USER_GID -u $USER_UID $USER_NAME

# Installing basic packages
RUN apt-get update && \
   apt-get install -y zip unzip curl && \
   rm -rf /var/lib/apt/lists/* && \
   rm -rf /tmp/*

# Switching to non-root user to install SDKMAN!
USER $USER_UID:$USER_GID

# Downloading SDKMAN!
RUN curl -s "https://get.sdkman.io" | bash

# Installing Java and Maven, removing some unnecessary SDKMAN files
RUN bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && \
    yes | sdk install java $JAVA_VERSION && \
    yes | sdk install maven $MAVEN_VERSION && \
    rm -rf $HOME/.sdkman/archives/* && \
    rm -rf $HOME/.sdkman/tmp/*"

ENV MAVEN_HOME="/home/jenkins/.sdkman/candidates/maven/current"
ENV JAVA_HOME="/home/jenkins/.sdkman/candidates/java/current"
ENV PATH="$MAVEN_HOME/bin:$JAVA_HOME/bin:$PATH"

The Jenkins Pipeline contains two stages - Build, and Install. The Build stage has two parallel stages inside. The first one compiles the Maven project using OpenJDK 8, while the second one uses OpenJDK 11. Keep in mind that this is just an illustration. You could use the same approach to compile your project using e.g., two different Maven versions, or different JDK vendors.

A pipeline with the parallel Java 8 and Java 11

You have seen the Dockerfile we are going to use to create the build environment docker image. Here is the pipeline’s Jenkinsfile.

Listing 2. Jenkinsfile (source)
pipeline {
    environment {
        DOCKERFILE = "Dockerfile.build"
    }

    stages {
        stage("Build") {
            environment {
                MVN_COMMAND = "mvn clean package"
                TEST_REPORTS = "target/surefire-reports/*.xml"
            }

            parallel {
                stage("openjdk-8.0.232") {
                    agent {
                        dockerfile { (1)
                            filename DOCKERFILE (2)
                            additionalBuildArgs "--build-arg JAVA_VERSION=8.0.232-open -t maven:8.0.232-open" (3)
                        }
                    }
                    steps {
                        sh "${MVN_COMMAND} -P jdk8" (4)
                    }
                    post {
                        always {
                            junit TEST_REPORTS
                        }
                    }
                }

                stage("openjdk-11.0.5") {
                    agent {
                        dockerfile {
                            filename DOCKERFILE
                            additionalBuildArgs "--build-arg JAVA_VERSION=11.0.5-open -t maven:11.0.5-open"
                        }
                    }
                    steps {
                        sh "${MVN_COMMAND} -P jdk11"
                    }
                    post {
                        always {
                            junit TEST_REPORTS
                        }
                    }
                }
            }
        }

        stage("Install") {
            agent {
                dockerfile {
                    filename DOCKERFILE
                    additionalBuildArgs "--build-arg JAVA_VERSION=8.0.232-open"
                    args '-v $HOME/.m2/repository:/home/jenkins/.m2/repository:rw,z' (5)
                }
            }
            steps {
                sh "mvn -DskipTests install -P jdk8"
            }
        }
    }
}

In this example, I used the Declarative Pipeline script. Each parallel stage inside the Build stage uses the dockerfile agent. The Dockerfile name is specified using environment variable DOCKERFILE which stores the Dockerfile.build name. We also pass the additional build arguments - a JAVA_VERSION one especially. In the Maven build command we add a specific profile like jdk8 and jdk11 to configure the Maven compiler plugin accordingly to the Java version.

The Install stage we use OpenJDK 8 only. This stage also uses the dockerfile agent, but this time we mount ~/.m2/repository from the docker host to the container, so the installed artifact will be persisted on the Jenkins node.

Executing the pipeline

Jenkins Pipeline with multiple Java versions using Maven, Docker, and SDKMAN! | #jenkinspipeline

In this video, I show you how you can use Jenkins Declarative Pipeline to create a build pipeline that compiles the Maven Java project using three different Java versions (8, 11, and 15.) You will learn how to use a matrix section of the Jenkins Pipeline to define parallel stages, as well as how to create a Docker image that provides both Java and Maven using the powerful SDKMAN command-line tool. Watch now »

  • java
  • docker
  • sdkman
  • jenkins
  • jenkins-pipeline
  • cicd
  • maven

Groovy Cookbook

Three Groovy String methods that will make your life Groovier!

  • December 18, 2019
  • 3 min. read
  • 0 Comments

Groovy String API offers many useful methods to make working with strings much more pleasant. Today I would like to show you three, not so very popular, yet convenient methods. Let’s jump straight into it!

Jenkins Pipeline Cookbook

Building Java and Maven docker images using parallelized Jenkins Pipeline and SDKMAN!

  • November 11, 2019
  • 3 min. read
  • 0 Comments

In the last article, I have shown you how you can build a docker image for Jenkins Pipeline usin...

Jenkins Pipeline Cookbook

Using SDKMAN! as a docker image for Jenkins Pipeline - a step by step guide

  • November 6, 2019
  • 3 min. read
  • 0 Comments

A few days ago, I was struggling with some Docker images I use in my Jenkins CI environment. I r...

Jenkins Pipeline Cookbook

Jenkins Pipeline Environment Variables - The Definitive Guide

  • November 2, 2019
  • 3 min. read
  • 0 Comments

Have you run into troubles when you started using Jenkins Environment Variables in your Jenkinsf...

Any thoughts or ideas?

Let's talk in the comment's section 💬

Want to put a code sample in the comment? Read the Syntax highlighting guide for more information.
Empty
Latest blog posts
  • Merging JSON files recursively in the command-line
  • Jenkins Declarative Pipeline with the dynamic agent - how to configure it?
  • Groovy Ecosystem Usage Report (2020)
  • How to convert JSON to CSV from the command-line?
  • 5 Common Jenkins Pipeline Mistakes
  • How to merge two maps in Groovy?
  • Building stackoverflow-cli with Java 11, Micronaut, Picocli, and GraalVM
  • How to catch curl response in Jenkins Pipeline?
  • Atomic Habits - book review
  • Parsing JSON in command-line with jq: basic filters and functions (part 1)
Trending videos
Jenkins Pipeline Environment Variables explained | #jenkinspipeline

In today's video, I show you how you can work effectively with environment variables in the Jenkins pipeline as a code. You w...

Jenkins Declarative Pipeline vs Scripted Pipeline - 4 key differences | #jenkinspipeline

Jenkins Pipeline as a code is a new standard for defining continuous integration and delivery pipelines in Jenkins. The scrip...

Useful links
  • Start here
  • About
  • Archives
  • Resources
  • Privacy Policy
  • Merchandise
  • My Kit
  • RSS
  • Support the blog
Popular categories
  • Groovy Cookbook28
  • Jenkins Pipeline Cookbook9
  • Programmer's Bookshelf6
  • Micronaut Cookbook4
  • Ratpack Cookbook4
  • Learning Java4
  • jq cookbook3
  • How to3
  • Blog Reports2
Popular tags
affiliate async benchmark blogging book career cicd continuous-integration curl devops docker git github graalvm gradle grails groovy haskell hexo java java-8 jenkins jenkins-pipeline jenkinsfile jmh jq json junit learning maven metaprogramming micronaut native-image non-blocking progress ratpack reactive-programming reading recursion review rxjava sdkman session split spock stackoverflow string tail-call tail-recursion unit-test
  • Designed by @wololock
  • Created with Hexo
  • Hosted on GitHub
  • Deployed with Circle CI
  • License CC BY-NC-SA 4.0