Jenkins Shared Library failed to reference - jenkins

I'm failing to reference a second groovy file in my src of my repo.
My set up is this: library name pipeline-library-demo
github
I have added a second groovy file to the src folder
app_config.groovy
#!/usr/bin/groovy
def bob(opt) {
sh "docker run --rm " +
'--env APP_PATH="`pwd`" ' +
'--env RELEASE=${RELEASE} ' +
"-v \"`pwd`:`pwd`\" " +
"-v /var/run/docker.sock:/var/run/docker.sock " +
"docker_repo/bob:1.4.0-8" ${opt}
}
def test(name) {
echo "Hello ${name}"
}
The Jenkins file I am using is:
pipeline {
Library('pipeline-library-demo') _
agent {
node {
label params.SLAVE
config = new app_config()
}
}
parameters {
string(name: 'SLAVE', defaultValue: 'so_slave')
}
stages {
stage('Demo') {
steps {
echo 'Hello World'
sayHello 'Dave'
}
}
stage('bob') {
steps {
config.test 'bob'
config.bob '--help'
}
}
}
}
I think I am not referencing the app_config.groovy correctly and it's not finding

Library call should come in starting of the jenkins file, please follow below
If you have added the library configuration in jenkins configuration then call should be like below:-
#Library('pipeline-library-demo')_
If you want to call the library dynamically you should call like below:-
library identifier: 'custom-lib#master', retriever:
modernSCM([$class:'GitSCMSource',remote:
'git#git.mycorp.com:my-jenkins-utils.git', credentialsId:
'my-private-key'])
please refer this link
And please define package in your app_config.groovy. (ex. package com.cleverbuilder)

Related

How to integrate Jenkins pipeline jobs and pass dynamic variables using Groovy?

I want to integrate Jenkins jobs using Groovy by passing dynamic variables based on the projects for which the job is triggered.
Can anyone please suggest on how to proceed with this?
Looks like you would like to persist data between two jenkins jobs or two runs of the same jenkins job. In both cases, I was able to do this using files. you can use write file to do it using groovy or redirection operator (>) to just use bash.
In first job, you can write to the file like so.
node {
// write to file
writeFile(file: 'variables.txt', text: 'myVar:value')
sh 'ls -l variables.txt'
}
In second job, you can read from that file and empty the contents after you read it.
stage('read file contents') {
// read from the file
println readFile(file: 'variables.txt')
}
The file can be anywhere on the filesystem. Example with a file created in /tmp folder is as follows. You should be able to run this pipeline by copy-pasting.
node {
def fileName = "/tmp/hello.txt"
stage('Preparation') {
sh 'pwd & rm -rf *'
}
stage('write to file') {
writeFile(file: fileName, text: "myvar:hello", encoding: "UTF-8")
}
stage('read file contents') {
println readFile(file: fileName)
}
}
You could also use this file as a properties file and update a property that exists and append ones that don't . A quick sample code to do that looks like below.
node {
def fileName = "/tmp/hello.txt"
stage('Preparation') {
sh 'pwd & rm -rf *'
}
stage('write to file') {
writeFile(file: fileName, text: "myvar:hello", encoding: "UTF-8")
}
stage('read file contents') {
println readFile(file: fileName)
}
// Add property
stage('Add property') {
if (fileExists(fileName)) {
existingContents = readFile(fileName)
}
newProperty = "newvar:newValue"
writeFile(file: fileName, text: existingContents + "\n" + newProperty)
println readFile(file: fileName)
}
}
You could easily delete a line that has a property if you would like to get rid of it

Read data in jenkinsfile from xml file created in current workspace

Some time ago I tried to connect jenkins and gerrit and send cppcheck output from jenkins to gerrit as comment:
I installed proper patches for jenkins and gerrit(that is ok it's work)
In jekinsfile I'm tried to run cppckeck and save it's output to xml file(it's works)
Problem is here that when I'm trying to read xml file, and I have information that there is no such file. I see that script have different root catalog(i groovy I printed dir). I think code with my experimental jenkinsfile explain problem:
pipeline {
agent any
stages {
stage('Example') {
steps {
gerritReview labels: [Verified: 0]
sh 'pwd'
sh 'cppcheck --enable=all --inconclusive --xml --xml-version=2 *.c* 2> cppcheck.xml'
script {
def parser = new XmlParser()
def doc = parser.parse("cppcheck.xml"); // No xml file here because script {}
// is run in different place
}
}
}
post {
always {
gerritReview score: 1
step([$class: 'CppcheckPublisher', pattern: 'cppcheck.xml', ignoreBlankFiles: false, treshold: "0"])
}
} }
How to load this file. Or I'm doing it's all wrong?(I mean integration gerrit with jenkins who purpose is to run cppcheck and cpplint and show results in gerrit).
If the file is in your repo, you need to check out the repo first
https://www.jenkins.io/doc/pipeline/steps/workflow-scm-step/
pipeline {
agent any
stages {
stage('Example') {
steps {
checkout scm // ADD THIS LINE
gerritReview labels: [Verified: 0]
sh 'pwd'
sh 'cppcheck --enable=all --inconclusive --xml --xml-version=2 *.c* 2> cppcheck.xml'
script {
def parser = new XmlParser()
def doc = parser.parse("cppcheck.xml");
}
}
}
post {
always {
gerritReview score: 1
step([$class: 'CppcheckPublisher', pattern: 'cppcheck.xml', ignoreBlankFiles: false, treshold: "0"])
}
}
}

How to correctly call a function in the declarative Jenkins file

Good day!
I would like to call a function that sets a a choice parameter with the list of folder in the branch. I getting null value at the end.
My Jenkins file looks like the below:
void findCollectionDirs() {
directories = sh (
script: "find . -path './[^.]*/*/*' -prune -type d",
returnStdout: true
)
return directories
}
def directories
pipeline () {
agent {
label 'slave'
}
triggers {
cron(cron_string)
}
parameters {
choice(choices: "\n" + directories, description: 'Please select a directory', name: 'directory')
}
stages {
stage ("Checkout scm") {
steps {
deleteDir()
checkout scm
//sh 'directories = findCollectionDirs()'
findCollectionDirs()
}
}
I tried by calling it as below:
sh 'directories = findCollectionDirs()'
or,
findCollectionDirs()
or
directories.findCollectionDirs()
but the value still null.
Can someone help me to call correctly the function so I get the right values in the choice parameter.
Thanks in advance

Jenkins Shared Library return executable docker command

Is it possible to get a shared library to retune a docker run command?
I have the following,
scr/docker_run.groovy
def ubuntu() {
echo "docker run --rm " +
'--env APP_PATH="`pwd`" ' +
'--env RELEASE=true ' +
"-v \"`pwd`:`pwd`\" " +
"-v /var/run/docker.sock:/var/run/docker.sock " +
"ubuntu"
}
Jenkinsfile
#Library('pipeline-library-demo') _
pipeline {
agent {
node {
label params.SLAVE
}
}
parameters {
string(name: 'SLAVE', defaultValue: 'so_slave')
}
stages {
stage('ubuntu') {
steps {
script {
sh docker_run.ubuntu ls -lah
}
}
}
}
}
I have tried different things inside the groovy file, such as echo, sh, call, all returning errors.
Any help would be great
If you are using DSL style pipeline you should define Steps in your shared library not directly a function in the src/ directory. Should follow the directory structure defined here https://jenkins.io/doc/book/pipeline/shared-libraries/
Then you can define a Step like
vars/mystep.groovy
def call() {
this.sh("docker_run.ubuntu ls -lah");
}
And calling from you pipeline as:
#Library('pipeline-library-demo') _
pipeline {
agent {
node {
label params.SLAVE
}
}
parameters {
string(name: 'SLAVE', defaultValue: 'so_slave')
}
stages {
stage('ubuntu') {
steps {
mystep
}
}
}
}
Best

Jenkinsfile Declarative Pipeline defining dynamic env vars

I'm new to Jenkins pipeline; I'm defining a declarative syntax pipeline and I don't know if I can solve my problem, because I didn't find a solution.
In this example, I need to pass a variable to ansible plugin (in old version I use an ENV_VAR or injecting it from file with inject plugin) that variable comes from a script.
This is my perfect scenario (but it doesn't work because environment{}):
pipeline {
agent { node { label 'jenkins-node'}}
stages {
stage('Deploy') {
environment {
ANSIBLE_CONFIG = '${WORKSPACE}/chimera-ci/ansible/ansible.cfg'
VERSION = sh("python3.5 docker/get_version.py")
}
steps {
ansiblePlaybook credentialsId: 'example-credential', extras: '-e version=${VERSION}', inventory: 'development', playbook: 'deploy.yml'
}
}
}
}
I tried other ways to test how env vars work in other post, example:
pipeline {
agent { node { label 'jenkins-node'}}
stages {
stage('PREPARE VARS') {
steps {
script {
env['VERSION'] = sh(script: "python3.5 get_version.py")
}
echo env.VERSION
}
}
}
}
but "echo env.VERSION" return null.
Also tried the same example with:
- VERSION=python3.5 get_version.py
- VERSION=python3.5 get_version.py > props.file (and try to inject it, but didnt found how)
If this is not possible I will do it in the ansible role.
UPDATE
There is another "issue" in Ansible Plugin, to use vars in extra vars it must have double quotes instead of single.
ansiblePlaybook credentialsId: 'example-credential', extras: "-e version=${VERSION}", inventory: 'development', playbook: 'deploy.yml'
You can create variables before the pipeline block starts. You can have sh return stdout to assign to these variables. You don't have the same flexibility to assign to environment variables in the environment stanza. So substitute in python3.5 get_version.py where I have echo 0.0.1 in the script here (and make sure your python script just returns the version to stdout):
def awesomeVersion = 'UNKNOWN'
pipeline {
agent { label 'docker' }
stages {
stage('build') {
steps {
script {
awesomeVersion = sh(returnStdout: true, script: 'echo 0.0.1').trim()
}
}
}
stage('output_version') {
steps {
echo "awesomeVersion: ${awesomeVersion}"
}
}
}
}
The output of the above pipeline is:
awesomeVersion: 0.0.1
In Jenkins 2.76 I was able to simplify the solution from #burnettk to:
pipeline {
agent { label 'docker' }
environment {
awesomeVersion = sh(returnStdout: true, script: 'echo 0.0.1')
}
stages {
stage('output_version') {
steps {
echo "awesomeVersion: ${awesomeVersion}"
}
}
}
}
Using the "pipeline utility steps" plugin, you can define general vars available to all stages from a properties file. For example, let props.txt as:
version=1.0
fix=alfa
and mix script and declarative Jenkins pipeline as:
def props
def VERSION
def FIX
def RELEASE
node {
props = readProperties file:'props.txt'
VERSION = props['version']
FIX = props['fix']
RELEASE = VERSION + "_" + FIX
}
pipeline {
stages {
stage('Build') {
echo ${RELEASE}
}
}
}
A possible variation of the main answer is to provide variable using another pipeline instead of a sh script.
example (set the variable pipeline) : my-set-env-variables pipeline
script
{
env.my_dev_version = "0.0.4-SNAPSHOT"
env.my_qa_version = "0.0.4-SNAPSHOT"
env.my_pp_version = "0.0.2"
env.my_prd_version = "0.0.2"
echo " My versions [DEV:${env.my_dev_version}] [QA:${env.my_qa_version}] [PP:${env.my_pp_version}] [PRD:${env.my_prd_version}]"
}
(use these variables) in a another pipeline my-set-env-variables-test
script
{
env.dev_version = "NOT DEFINED DEV"
env.qa_version = "NOT DEFINED QA"
env.pp_version = "NOT DEFINED PP"
env.prd_version = "NOT DEFINED PRD"
}
stage('inject variables') {
echo "PRE DEV version = ${env.dev_version}"
script
{
// call set variable job
def variables = build job: 'my-set-env-variables'
def vars = variables.getBuildVariables()
//println "found variables" + vars
env.dev_version = vars.my_dev_version
env.qa_version = vars.my_qa_version
env.pp_version = vars.my_pp_version
env.prd_version = vars.my_prd_version
}
}
stage('next job') {
echo "NEXT JOB DEV version = ${env.dev_version}"
echo "NEXT JOB QA version = ${env.qa_version}"
echo "NEXT JOB PP version = ${env.pp_version}"
echo "NEXT JOB PRD version = ${env.prd_version}"
}
For those who wants the environment's key to be dynamic, the following code can be used:
stage('Prepare Environment') {
steps {
script {
def data = [
"k1": "v1",
"k2": "v2",
]
data.each { key ,value ->
env."$key" = value
// env[key] = value // Deprecated, this can be used as well, but need approval in sandbox ScriptApproval page
}
}
}
}
You can also dump all your vars into a file, and then use the '-e #file' syntax. This is very useful if you have many vars to populate.
steps {
echo "hello World!!"
sh """
var1: ${params.var1}
var2: ${params.var2}
" > vars
"""
ansiblePlaybook inventory: _inventory, playbook: 'test-playbook.yml', sudoUser: null, extras: '-e #vars'
}
You can do use library functions in the environments section, like so:
#Library('mylibrary') _ // contains functions.groovy with several functions.
pipeline {
environment {
ENV_VAR = functions.myfunc()
}
…
}

Resources