Preparations for the sample workflow
Let’s start with setting up the tools. Go to the Jenkins configuration > Global Tool Configuration and find the Maven section at the bottom.
Click on the ‘Maven installations’ button to expand the section.
Enter the name ‘Maven_3_5’: we will select the tool later on in the pipeline using this name. We want to have automatic installation enabled, and we select the most recent version of the 3.5 branch. Selecting an explicit version makes sure that you don’t unexpectedly get broken builds because the maven team pushed a new release which breaks backward compatibility.
Save your config and return to the Jenkins configuration menu.
Once we start building, we will be down- and uploading artifacts from Nexus. For this, we’ll need credentials. In the menu on the left side of your screen, you’ll find the ‘Credentials’ item. Click it so that it shows ‘System’. Click ‘System’ and you will navigate to a screen where you see ‘Global credentials (unrestricted)’ in the center of your screen. Click that link to open the screen where you can ‘Add Credentials’.
Create a useraccount in Jenkins
Select a ‘username with password’ type of account, and provide your credentials. A good description will help you when you need to select the credentials from a long list.
Store your changes and return to the main screen.
We will be using some plugins that are not installed by default. Go to the ‘Plugin Manager’ screen to install them.
Navigate to the ‘Available’ tab and select “Config File Provider” and “Pipeline Maven Integration”. Make sure to ‘Download now and install after restart’, so that the plugin is active.
Global settings for Maven
Go to ‘Magaged Files’ > ‘Add a new config’ to create a global maven configuration file.
A unique ID will be generated, you should not edit it. Enter the name ‘MyGlobalSettings’ and a comment. Make sure Replace All is selected, so that the credentials in the settings file will be overwritten by Jenkins. We want the secure store in Jenkins to hold the credentials. All plain text settings files like this one should not contain any sensitive information.
Since we have two server declarations in our settings file, we need to add two credential sets. Both instances will use the same credentials: select the nexus credentials we made earlier.
Finally, copy-paste the settings file below into the content box and ‘Submit’ your changes.
<?xml version="1.0" encoding="UTF-8"?>
This file defines some settings for all our maven builds:
- It defines a cache folder on the slave where all builds share their plugin and artifact downloads
- It defines credentials for two artifact repositories. The passwords here are not used, they are overwritten by Jenkins using the Server Credentials we entered in the screenshot above.
- We define a mirror site, so that all downloads will pass through our own Nexus repository. Nexus will return our private artifacts, or when it doesn’t have the artifact, it will search on maven central for a download, and it will cache it. This behavior is specified in our Nexus setup.
User settings for Maven
The user settings for maven is the place where you should put project specific setup. For me, my global setup is good enough, so my file is mostly empty.
Copy the following content into the file:
<?xml version="1.0" encoding="UTF-8"?>
<!-- MySettings -->
There are no server entries in this file, so we don’t need to overrule Server Credentials by ‘Add’-ing them. Just save the config and continue.
Activate the global settings.xml
Go to Global tool configuration > Maven Configuration > Default Global Settings Provider and select the config file Myglobalsettings
Prepare a sample workflow project
In order to verify our setup, we will need something to build. I have chosen a very basic Java program to showcase the build.
Start by creating a git repository on your favorite host, and clone the git repo so that you can start working. Inside the root of the project, we call:
mvn archetype:generate -DgroupId=java_sample -DartifactId=sample -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
This creates a basic java program, with a single unit test. No need to go into an editor yet to write a program.
Add a pom in the root folder:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
We define two important parts:
- In repositories we define where Maven can find any dependency it needs to build the project. All downloads will be from this repository. We use our public nexus repository, which searches our releases, snapshots and if still nothing is found, it will try to download from maven central.
- In distribution management, the destinations for our artifacts are defined. When we do a snaphot build, we upload to maven-snapshots in nexus, and we we do a release, the file is uploaded to maven-releases.
Furthermore, we define the folder sample as a module, so that it will get build recursively, and we define the maven-release-plugin. We are not going into the details of setting up the Java project, as that is outside of the scope for this post.
Before continuing, you should validate your build locally. Try “mvn install” in your workdir and see what happens. If you get download errors, make sure that nexus resolves to your machine, for example by adding the line “127.0.0.1 nexus” to your hosts file.
Add the following Jenkinsfile:
sh 'mvn clean deploy'
In the above sample, replace the id d4b07913-04d5-48c5-9c0e-292b565f152e by the id of your second settings file from the Jenkins Config File plugin.
The Jenkinsfile defines your pipeline. We start out by declaring that we will explicitly set the agent in every step, and our pipeline makes use of the Maven 3.5 tool which we setup previously in the Jenkins tools config.
The build consists of stages: visually separate actions in the sequence of actions to build and deploy your program. has only one stage for now: the Build stage. For this stage, we need to run on a slave agent that has the label ‘slave-java-11’. During the stage, we can have multiple steps, but we only need one: we need the maven tool and a config file from the Files plugin in Jenkins in order to execute a single shell command: “mvn clean deploy”, which will build, unit-test and upload to Nexus.
You should now have the following structure:
Commit and push.
Create your first Jenkins build
- Create credentials for your Git user.
- Create a new build job for this git repo: multi branch pipeline
- Link it to your repo
Screenshot of a successful build in Jenkins pipeline
Select ‘Scan Multibranch Pipeline Now’ on the root of your project to let Jenkins find all branches and execute a build job for each new branch it finds.
I enabled mvn debugging (mvn -X clean deploy) to see which settings.xml were used. It shows both the global settings as the user settings:
[DEBUG] Reading global settings from /opt/workspace/java_sample_develop-TDM3SN5C526GKQJCW7Y5YCZ7F3QNYB4LBZ6FVYCHSEUMOS72ZOPQ@tmp/withMaven85e33fb7/globalSettings.xml
[DEBUG] Reading user settings from /opt/workspace/java_sample_develop-TDM3SN5C526GKQJCW7Y5YCZ7F3QNYB4LBZ6FVYCHSEUMOS72ZOPQ@tmp/withMaven85e33fb7/settings.xml
Your first build should now run successfully. This concludes our sample workflow.
In our next post, we will start checking the quality of the program using SonarQube.