JAVA_HOME not found Maven Docker image Jenkins pipeline - jenkins

I am receiving a message that JAVA_HOME can't be found or is pointed to a JRE when running the following in a Jenkins Declarative Pipeline.
pipeline {
agent none
stages {
stage('Build and Package') {
agent {
docker { image 'maven:3.5.2-jdk-8' }
}
steps {
sh 'mvn clean verify'
}
}
}
}

See Installing Apache Maven:
Ensure JAVA_HOME environment variable is set and points to your JDK installation

Related

Jenkins Pipeline with Dockerfile configuration

I am struggling, to get the right configuration for my Jenkins Pipeline.
It works but I could not figure out how to seperate test & build stages.
Requirements:
Jenkins Pipeline with seperated test & build stage
Test stage requires chromium (I currently use node alpine image + adding chromium)
Build stage is building a docker image, which is published later (publish stage)
Current Setup:
Jenkinsfile:
pipeline {
environment {
...
}
options {
...
}
stages {
stage('Restore') {
...
}
stage('Lint') {
...
}
stage('Build & Test DEV') {
steps {
script {
dockerImage = docker.build(...)
}
}
}
stage('Publish DEV') {
steps {
script {
docker.withRegistry(...) {
dockerImage.push()
}
}
}
}
Dockerfile:
FROM node:12.16.1-alpine AS build
#add chromium for unit tests
RUN apk add chromium
...
ENV CHROME_BIN=/usr/bin/chromium-browser
...
# works but runs both tests & build in the same jenkins stage
RUN npm run test-ci
RUN npm run build
...
This works, but as you can see "Build & Test DEV" is a single stage,
I would like to have 2 seperate jenkins stages (Test, Build)
I already tried using Jenkins agent docker and defining the image for the test stage inside the jenkins file, but I dont know how to add the missing chromium package there.
Jenkinsfile:
pipeline {
agent {
docker {
image 'node:12.16.1-alpine'
//add chromium package here?
//set Chrome_bin env?
}
}
I also thought about using a docker image that already includes chromium, but couldnt find any official images
Would really appreciate your help / insights how to make this work.
You can either build your customized image (which includes the installation of Chromium) and push it to a registry and then pull it from that registry:
node {
docker.withRegistry('https://my-registry') {
docker.image('my-custom-image').inside {
sh 'make test'
}
}
}
Or build the image directly with Jenkins with your Dockerfile:
node {
def testImage = docker.build("test-image", "./dockerfiles/test")
testImage.inside {
sh 'make test'
}
}
Builds test-image from the Dockerfile found at ./dockerfiles/test/Dockerfile.
Reference: Using Docker with Pipeline
So in general I would execute the npm run commands inside the groovy syntax and not inside the dockerfile. So your code would look something like that:
pipeline {
agent {
docker {
image 'node:12.16.1-alpine'
args '-u root:root' // better would be to use sudo, but this should work
}
}
stages {
stage('Preparation') {
steps {
sh 'apk add chromium'
}
}
stage('build') {
steps {
sh 'npm run build'
}
}
stage('test') {
steps {
sh 'npm run test'
}
}
}
}
I would also suggest that you collect the results within Jenkins with the warnings ng jenkins plugin

Pass maven argument in jenkins pipeline shell command

I have a doubt on the below issue can someone please help me on this.
I wanted to pass maven pom.xml properties from the shell in jenkins pipeline which needs to be substituted by maven and not by groovy or shell.
Example:
pipeline {
agent any
stages {
stage('build') {
steps {
sh 'mvn -Doracle.db.url=${db.url} package'
}
}
}
}
Here ${db.url} should be substituted by the url from maven setting.xml file properties and not by groovy or shell in Jenkins pipeline.
I have tried different combination but it gives me error in Jenkins pipeline.
If the above maven property is constant(some constant url) then it is easy to pass but when I wanted to pass any variable property (${db.url}) then I am not able to do so with any syntax.
If you want maven to evaluate ${db.url}, it has to be like
pipeline {
agent any
stages {
stage('build') {
steps {
sh 'mvn -Doracle.db.url=\\${db.url} package'
}
}
}
}
Now if you see, Jenkins will prepare the maven command like this-
If you don't escape it will give you Bad substitution error

Jenkins declarative pipeline: npm command not found

So I have set up this jenkins ec2 instance, ssh into it, globally installed node and set PATH. But when executing my pipeline, it gives me npm command not found error.
I put echo $PATH in my pipeline and the result is:
/home/ec2-user/.nvm/versions/node/v10.15.1/bin:/sbin:/usr/sbin:/bin:/usr/bin
Which looks correct.
For reference, here's my very simple pipeline:
pipeline {
agent { label 'master' }
environment {
PATH = "/home/ec2-user/.nvm/versions/node/v10.15.1/bin:${env.PATH}"
}
stages {
stage('Test npm') {
steps {
sh """
echo $PATH
npm --version
"""
}
}
}
}
Appreciate with any help.
As #Dibakar Adtya pointed, the problem is when jenkins executes a pipeline, it's under the user jenkins, whereas I configured node under another user, ec2-user, and jenkins doesn't have access to ec2-user's bin. Thank you #Dibakar!
A more elegant solution is to use Jenkins NodeJS Plugin. It saves you from the environment hassles. Now the pipeline is:
pipeline {
agent { label 'master' }
tools { nodejs "nodejs" }
stages {
stage('Test npm') {
steps {
sh """
npm --version
"""
}
}
}
}

Maven pipeline fails to find JDK

I have a problem running a simple Java Maven pipeline. The used maven command fails using the expected JDK for an unknown reason.
freshly installed Jenkins running from the docker image jenkinsci/blueocean:latest
configured Oracle JDK 9 and Maven 3.5.4 at the Jenkins Tools settings pane
Jenkinsfile content:
pipeline {
agent any
tools {
jdk 'java9'
maven 'Maven3.5'
}
stages {
stage ('Initialize') {
steps {
sh '''
echo "PATH = ${PATH}"
echo "M2_HOME = ${M2_HOME}"
echo "JAVA_HOME = ${JAVA_HOME}"
'''
}
}
stage ('Build') {
steps {
sh 'java -version'
sh 'mvn --version'
}
}
}
}
Output of the "Initialize" stage script
PATH = /var/jenkins_home/tools/hudson.model.JDK/java9/bin:/var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/Maven3.5/bin:/var/jenkins_home/tools/hudson.model.JDK/java9/bin:/var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/Maven3.5/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin
M2_HOME = /var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/Maven3.5
JAVA_HOME = /var/jenkins_home/tools/hudson.model.JDK/java9
This looks valid to me. M2_HOME and JAVA_HOME point to the expected path of the Jenkins tools.
Output of the "Build" "java -version" script
+ java -version
openjdk version "1.8.0_191"
OpenJDK Runtime Environment (IcedTea 3.10.0) (Alpine 8.191.12-r0)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)
This seems to be the installed Java of the Jenkins docker host system
Failure output of the "Build" "mvn -version" script:
mvn --version
/var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/Maven3.5/bin/mvn: exec: line 191: /var/jenkins_home/tools/hudson.model.JDK/java9/bin/java: not found
script returned exit code 127
If I bash into the Jenkins docker container, I find the java bin at the mentioned path.
Where is my mistake? Why can't Maven find the Java?
Is it a permission problem? Jenkins docker container uses a docker volume:
-v jenkins-data:/var/jenkins_home.
Best,
Lars
Not sure tools + docker in Jenkins Pipeline is working so good.
See: https://issues.jenkins-ci.org/browse/JENKINS-36159
Only way so far I've managed to get this to work was by mounting the docker node's tools directory into the docker slave.
e.g.
agent { docker
args '-v $HOME/tools:/var/lib/jenkins/tools'
stage { step {
sh "${MAVEN_HOME}/bin/mvn -version"
EDIT: Just found this too: https://issues.jenkins-ci.org/browse/JENKINS-48050
You don't need both tools. It is enough with Maven tool. It includes Java. Your pipeline should be:
pipeline {
agent any
tools {
maven 'Maven3.5'
}
stages {
stage ('Initialize') {
steps {
sh '''
echo "PATH = ${PATH}"
echo "M2_HOME = ${M2_HOME}"
echo "JAVA_HOME = ${JAVA_HOME}"
'''
}
}
stage ('Build') {
steps {
sh 'java -version'
sh 'mvn --version'
}
}
}
}
And you can delete Java Tool in Jenkins configuration tool.
This problem occurs when you're using an alpine based docker image for jenkins and your jdk is glibc based. You can solve this in two ways:
Use a jdk that is musl based. You can find them on adoptium by filtering out the OS as Alpine Linux.
Use a non-alpine based docker image.

Running SonarQube Scanner on a Jenkins remote slave

I have a Docker container running Jenkins (2.150.1) and another Docker container running SonarQube (7.4). Jenkins is using the SonarQube Scanner for Jenkins plugin and the scanning is done on the Jenkins container. The Jenkinsfile for the project looks like this:
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'building...'
}
}
stage('Test') {
steps {
echo 'testing...'
withSonarQubeEnv ('SonarQube') {
sh '/var/jenkins_home/sonar-scanner/sonar-scanner-3.2.0.1227-linux/bin/sonar-scanner'
}
echo 'really finished testing2'
}
}
stage("Quality Gate") {
steps {
timeout(time: 1, unit: 'MINUTES') {
waitForQualityGate abortPipeline: true
}
}
}
stage('Deployment') {
steps {
echo 'deploying...'
}
}
}
}
To get the scanning to work as part of a Jenkins pipeline job, I manually installed sonar-scanner on the Jenkins container by downloading the zip file and unzipping it to: /var/jenkins_home/sonar-scanner/sonar-scanner-3.2.0.1227-linux
This is working well, but I want to improve it by:
taking out the harcoded path to sonar-scanner from my Jenkinsfile
specify a non local location of sonar-scanner because I now need to run the scan on another VM/container instead of on the Jenkins container
I tried using Manage Jenkins > Global Tool Configuration > SonarQube Scanner and updated my Jenkinsfile to use SONAR_RUNNER_HOME instead of the hard coded path, but that didn't work and I got an error that sonar-scanner can't be found.
In Manage Jenkins > Global Tool Configuration > SonarQube Scanner check install automatically.
Then go to Manage Jenkins > Configure System and add the following
The Name should be the same as the parameter in the line in your Jenkinsfile: withSonarQubeEnv('SonarQube')

Resources