How to change a Jenkins Declarative Pipeline environment variable? - jenkins

I'm trying to create some Docker images. For that I want to use the version number specified in the Maven pom.xml file as tag. I am however rather new to the declarative Jenkins pipelines and I can't figure out how to change my environment variable so that VERSION contains the right version for all stages.
This is my code
#!groovy
pipeline {
tools {
maven 'maven 3.3.9'
jdk 'Java 1.8'
}
environment {
VERSION = '0.0.0'
}
agent any
stages {
stage('Checkout') {
steps {
git branch: 'master', credentialsId: '290dd8ee-2381-4c5b-8d33-5631d03ee7be', url: 'git#gitlab.crosslang.local:company/SOME-API.git'
sh "git clean -f && git reset --hard origin/master"
}
}
stage('Build and Test Java code') {
steps {
script {
def pom = readMavenPom file: 'pom.xml'
VERSION = pom.version
}
echo "${VERSION}"
sh "mvn clean install -DskipTests"
}
}
stage('Build Docker images') {
steps {
dir('whales-microservice/src/main/docker'){
sh 'cp ../../../target/whales-microservice-${VERSION}.jar whales-microservice.jar'
script {
docker.build "company/whales-microservice:${VERSION}"
}
}
}
}
}
}

The problem is the single quote of the statement
sh 'cp ../../../target/whales-microservice-${VERSION}.jar whales-microservice.jar'
single quotes don't expand variables in groovy: http://docs.groovy-lang.org/latest/html/documentation/#_string_interpolation
so you have to double quote your shell statement:
sh "cp ../../../target/whales-microservice-${VERSION}.jar whales-microservice.jar"

I just wanted to mention that if you have pipeline-utility-steps plugin installed you can use readMavenPom() in the environment part, too. It looks like this:
environment {
VERSION = readMavenPom().getVersion()
}

Related

Inject Jenkins Variable to maven using Declarative Pipeline

I am Unable to add the above circled functionality in attached image as Declarative Pipeline Syntax.
PS I am new to this, i Searched for this on others answers but no one matches my requirements.
For example if there is a Parameter in jenkins named VERSION, maven command should become
clean deploy -B -s pathtosettings.xml -DVERSION=valueinparameter
Below is my current code
NOte : I WANT ALL THE PARAMETERS AUTOMATICALLY -DVERSION=${params.VERSION} doesnt help me
pipeline {
agent any
stages {
stage('Checkout Scm') {
steps {
git 'ssh://git#XXXXXXXXXXXXXXXXXXXXXXXXX.git'
}
}
stage('Maven Build 0') {
steps {
configFileProvider([configFile(fileId:'0c0631a5-6510-4b4a-833d-4b80fa67d5f3', targetLocation: 'settings.xml', variable: 'SETTINGS_XML')]) {
withMaven{
sh "mvn clean deploy -B -s ${SETTINGS_XML}
}
}
}
}
tools {
jdk 'JDK_1.8'
}
parameters {
string(name: 'VERSION', defaultValue: '3_12_0', description: 'version to be in maven')
}
}
First, I think you doesn't need targetLocation to perform this.
To access to your parameter value, you need to use params prefix.
This is how I'm using the configFileProvider to make it work :
configFileProvider([configFile(fileId: 'configFileId', variable: 'SETTINGS_XML')]) {
sh "mvn clean deploy -s \$SETTINGS_XML -B -DVERSION=$params.VERSION"
}
With this, the variable which link the settings file is not replaced and it's correctly used in my pipeline and the version is replaced in the command. Don't forget to use a
'Maven settings.xml' type of file in the configFileProvider.
steps {
script{
foo= " "
params.each {param ->
foo = "${foo} -D${param.key}=${param.value} "
}
}
configFileProvider([configFile(fileId:'XXXX', targetLocation: 'settings.xml', variable: 'SETTINGS_XML')]) {
withMaven{
sh "mvn clean deploy -B -s ${SETTINGS_XML} - ${foo}"
}
}
This is the Only Approach found

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
"""
}
}
}
}

Prevent Archiving In a Jenkins Pipeline

I have asked this question on the Jenkins mailing list.
I have an upstream component, libraryA, I build, archive, and deploy via a Maven job, jobA. This works great. I have a downstream Maven job, jobB, that has a dependency on libraryA. This also works great, except…
I have a completely separate pipeline job, pipelineA specified by Jenkinsfile. Within that Jenkinsfile, I build a specific branch of libraryA I don’t want archived or deployed. In my Jenkinsfile I have “withMaven(mavenLocalRepo: ‘libraryA/.repository’, publisherStrategy: ‘EXPLICIT’)”, and inside that, “sh “””[…]mvn clean package sonar:sonar[…]””” (Any typos here are probably the fault of my typing here as I did not copy-paste. There are no errors from Jenkins when executing these steps.) I have also tried “options: [artifactsPublisher(disabled: true)]” in place of “publisherStrategy: ‘EXPLICIT’” and had the same results. I have verified when pipelineA builds libraryA, it does NOT get deployed to my remote Maven repository, and I expect it not to get deployed there. Good.
So, what happens?
Well, if I build pipelineA followed by jobB, jobB gets its copy of libraryA from pipelineA, causing the build to fail. If I then run jobA, jobB succeeds as expected.
I could change the version of libraryA in the branch pipelineA builds, but I’d rather not do that as it’s not correct for my particular use case. What else could I do? What did I miss? (I do not admin this Jenkins instance, so my access is limited in that respect.)
For clarity here is an approximation of the pipeline's Jenkinsfile:
#!groovy
pipeline {
environment {
GIT_CREDENTIAL_ID = 'git_credential_name'
}
agent any
tools {
maven 'internal_maven'
jdk 'openjdk'
git 'internal_git'
}
stages {
stage('Build Parent') {
steps {
checkoutRepos([[checkoutDir: 'parent', branch: 'gold', url: 'ssh://git#fake-git-url/parent.git']], env.GIT_CREDENTIAL_ID)
withMaven(publisherStrategy: 'EXPLICIT') {
sh """
cd parent
mvn -U clean verify
"""
}
stash name: 'parent', includes: 'pom.xml'
}
}
stage('Build libraryParent') {
steps {
unstash 'parent'
checkoutRepos([[checkoutDir: 'libraryParent', branch: 'gold', url: 'ssh://git#fake-git-url/libraryParent.git']], env.GIT_CREDENTIAL_ID)
withMaven(mavenLocalRepo: 'libraryParent/.repository', publisherStrategy: 'EXPLICIT') {
sh """
mvn install:install-file -Dpackaging=pom -Dfile=pom.xml -DpomFile=pom.xml
cd libraryParent
mvn clean verify -P jacoco sonar:sonar -U -Dsonar.host.url=https://fake-sonar-url -Dsonar.scm.provider=git
"""
}
dir('libraryParent/libraryA/target/') {
stash name: 'libraryA', includes: 'libraryA-1000-SNAPSHOT.jar'
}
}
}
stage('Build appA') {
steps {
sonarAnApp 'appA'
}
}
stage('Build appB') {
steps {
sonarAnApp 'appB'
}
}
stage('Build appC') {
steps {
sonarAnApp 'appC'
}
}
}
}
def sonarAnApp(final String appName) {
unstash 'parent'
unstash 'libraryA'
checkoutRepos([[checkoutDir: appName, branch: 'gold', url: "ssh://git#fake-git-url/${appName}.git"]], env.GIT_CREDENTIAL_ID)
withMaven(mavenLocalRepo: "$appName/.repository", publisherStrategy: 'EXPLICIT') {
sh """
mvn install:install-file -Dpackaging=pom -Dfile=pom.xml -DpomFile=pom.xml
mvn install:install-file -Dfile=libraryA-1000-SNAPSHOT.jar
cd $appName
mvn clean verify -P jacoco sonar:sonar -U -Dsonar.host.url=https://fake-sonar-url -Dsonar.scm.provider=git
"""
}
}

Clone Jenkinsfile by changing default workspace from master to slave

I am working on Jenkins Pipeline Script and I have checked-in my jenkinsfile in Git repository and I need to clone to local work space. But by default its cloning to master (Unix) work space but I need it in slave (Windows) work space.
Is there any plugins to change the default Pipeline Script from SCM work space location to slave?
You can do something like this
pipeline {
agent any
options {
skipDefaultCheckout()
}
stages {
stage('checkout') {
steps {
node('windows') {
checkout scm
}
}
}
}
}
OR
pipeline {
agent 'windows'
stages {
stage('build') {
steps {
// build
}
}
}
}
In my case, the following pipeline configuration skips the default checkout on master, and checkout my code just on Jenkins slave.
node {
docker.image('php7.1.30:1.0.0').inside {
skipDefaultCheckout() // this avoid the checkout on master
stage("checkout"){
checkout scm // here the checkout happens on slave node
}
stage('NPM Install'){
sh label: 'NPM INSTALL', script: "npm install"
sh label: 'GRUNT INSTALL', script: "npm install -g grunt-cli"
}
stage('Executing grunt') {
sh label: 'GRUNT DEFAULT', script: "grunt default"
}
}
}

Using Jenkins to deploy to staging and production based on condition

My project has a Jenkinsfile that runs smoothly. The problem is that I need to run some commands only on certain occasions. I'm using the Github plugin. I need to run the deploy only when it is in the master or a new tag, one will be for staging and the other will be production.
pipeline {
agent any
stages {
stage('Test') {
steps {
sh 'node -v'
sh 'yarn install'
sh 'yarn test -- --coverage'
}
}
stage('Build') {
steps {
sh 'yarn build'
}
}
stage('Deploy') {
steps {
sh 'aws s3 sync ./build s3://my.bucket --only-show-errors'
}
}
}
}
I need the master to deploy to a bucket and when it is new tag to another. How can I create this conditional?
How about the following working as two conditionals for two separate deployment scenarios? I think it's better to work with this using variables to indicate deployment scenarios instead of splitting this to two distinctly different steps though. You could for example write a shell script that would handle everything inside depending on tags/branches/whatever you need instead of forcing yourself to control this on pipeline level.
Each stage will have it's steps executed only when when part is satisfied. Stage Deploy will only work for master branch, while stage Deploy_NonMaster will only work any non master branch. Using the method written in when conditionals you can check for anything, including tags or whatnot.
stage ('Deploy') {
when {
expression {
GIT_BRANCH = sh(returnStdout: true, script: 'git rev-parse --abbrev-ref HEAD').trim()
return (GIT_BRANCH == 'master')
}
}
steps {
echo 'Do stuff/deploy.'
}
}
stage ('Deploy_NonMaster') {
when {
expression {
GIT_BRANCH = sh(returnStdout: true, script: 'git rev-parse --abbrev-ref HEAD').trim()
return !(GIT_BRANCH == 'master')
}
}
steps {
echo 'Do stuff/deploy.'
}
}

Resources