Issue with loop in Jenkinsfile - jenkins-pipeline

I a variable in my Jenkinsfile that contains a list of URLs and i would like a be able to run over them. When i pass the variable $URL to the function, I get an error:
No such property: $URL for class: groovy.lang.Binding
However, I'm able to echo this variable with sh.
pipeline {
agent any
environment {
URL="https://www.aaa.com," \
+ "https://www.bbb.com," \
+ "https://www.ccc.com"
}
stages {
stage ('A') {
//...
}
stage ('B') {
//...
}
stage ('C') {
steps {
script {
sh 'echo $URL'
funcion($URL)
}
}
}
}
}
def funcion(URL) {
sh "echo Going to echo a list"
for (int i = 0; i < URL.size(); i++) {
sh "echo ${URL[i]}"
}
}
What could be the issue?

You should pass this variable to the funcion() method as
function(URL)
instead of
funcion($URL)
The dollar sign $ is used only inside the GString when you want to interpolate a variable. For instance
#!groovy
def name = "Joe"
println "My name is $name"
results in
My name is Joe
You can read more about string interpolation in the Groovy documentation - http://groovy-lang.org/syntax.html#_string_interpolation

Related

Jenkins pipeline multiline script command as variable

how can I save a command in a variable and executed anywhere in the stage
tried differnt way, but still success
here is my example
pipeline {
agent any
environment {
myscript = sh '''
echo "hello"
echo "hello"
echo "hello"
'''
}
stages {
stage("RUN") {
steps {
sh "${myscript}"
}
}
}
}
you can do it like this. Not with a groovy variable but can be more dynamic with groovy function/method
def reusableScript(message) {
sh """
echo Hello World
echo Hi ${message}
"""
}
pipeline {
agent any;
stages {
stage('01') {
steps {
script {
reusableScript("From ${env.STAGE_NAME}")
}
}
}
stage('02') {
steps {
script {
reusableScript("From ${env.STAGE_NAME}")
}
}
}
}
}

Set variables in a list in Declarative Jenkinsfile

I have set some environment variables as below :
environment {
IMG_TARGET = "registry/cloud-environemnt-azu:1.x.x"
CREDENTIALS = 'credentials-token'
BUILD_DIR = 'Builddir'
DOMAIN_DIR = 'Domaindir'
BUILD_SOLUTION = 'Dir.Builddir.sln'
}
Some variables are used throughout the Jenkins pipeline and I am looking to separate them from environment variables, such that only credentials and image target are in environment variables.
Is there a way I can use global list/variable/map to store non-environment variables, like :
List<String> variables = [
BUILD_DIR = 'Builddir'
DOMAIN_DIR = 'Domaindir'
BUILD_SOLUTION = 'Dir.Builddir.sln'
]
If so, how can I refer a variable from this list? The variables are being referenced across multiple stages in the pipeline
You can have an environment section for your pipeline and if needed, within each stage define a new environment section to override exisiting variables or define new ones. Example:
pipeline {
agent any
environment {
FOO = "bar"
NAME = "Joe"
}
stages {
stage("Env Variables") {
environment {
NAME = "Alan" // overrides pipeline level NAME env variable
BUILD_NUMBER = "2" // overrides the default BUILD_NUMBER
}
steps {
echo "FOO = ${env.FOO}" // prints "FOO = bar"
echo "NAME = ${env.NAME}" // prints "NAME = Alan"
echo "BUILD_NUMBER = ${env.BUILD_NUMBER}" // prints "BUILD_NUMBER = 2"
script {
env.SOMETHING = "1" // creates env.SOMETHING variable
}
}
}
stage("Override Variables") {
steps {
script {
env.FOO = "IT DOES NOT WORK!" // it can't override env.FOO declared at the pipeline (or stage) level
env.SOMETHING = "2" // it can override env variable created imperatively
}
echo "FOO = ${env.FOO}" // prints "FOO = bar"
echo "SOMETHING = ${env.SOMETHING}" // prints "SOMETHING = 2"
withEnv(["FOO=foobar"]) { // it can override any env variable
echo "FOO = ${env.FOO}" // prints "FOO = foobar"
}
withEnv(["BUILD_NUMBER=1"]) {
echo "BUILD_NUMBER = ${env.BUILD_NUMBER}" // prints "BUILD_NUMBER = 1"
}
}
}
}
}
Another option is to use parameterised jobs in declarative pipelines and if you're interested, you can read more here.
You can set environment variable specific to each stage by including environment block within the stage like below.
pipeline {
agent any
stages {
stage ("Test Stage"){
environment {
TEST_VARIABLE=test
}
steps {
echo "Hello"
}
}
}
}
If you want all non environment variable into single component then you can use map instead of List, as map will store the data in key value pair and you can retrieve any key at any point of time, with List you cannot store the value as a key value pair.
pipeline {
agent any
stages {
stage ("Test Stage"){
steps {
script {
def testMap = [BUILD_DIR:'Builddir',DOMAIN_DIR:'Domaindir',BUILD_SOLUTION:'Dir.Builddir.sln']
testMap.each {
entry -> echo "${entry.key}"
}
echo "${testMap['DOMAIN_DIR']}"
}
}
}
}
}
Thanks,

Jenkins pipeline RejectedAccessException error

I am trying to setup a jenkins pipeline script that sends out an email when there is a job that have been running for more than 24 hours.
// Long running jobs
pipeline {
agent any
environment {
EMAIL_ALERT_TO = "address"
EMAIL_ALERT_CC = "address"
}
stages {
stage('def methods') {
steps {
script {
Jenkins.instance.getAllItems(Job).each(){ job -> job.isBuildable()
if (job.isBuilding()){
def myBuild= job.getLastBuild()
def runningSince= groovy.time.TimeCategory.minus( new Date(), myBuild.getTime() )
echo "myBuild = ${myBuild}"
echo "runningSince = ${runningSince}"
env.myBuild = myBuild
env.runningSince = runningSince
}
}
}
}
}
}
post {
// Email out the results
always {
script {
if (runningSince.hours >= 1){
mail to: "${env.EMAIL_ALERT_CC}",
cc: "${env.EMAIL_ALERT_CC}",
subject: "Long Running Jobs",
body: "Build: ${myBuild} ---- Has Been Running for ${runningSince.hours} hours:${runningSince.minutes} minutes"
}
}
}
}
}
I am seeing RejectedAccessException which appears to be related to arrays/list.
This is what I believe you are looking for
https://issues.jenkins-ci.org/browse/JENKINS-54952?page=com.atlassian.jira.plugin.system.issuetabpanels%3Achangehistory-tabpanel

Fail Jenkins pipeline stage if some file contains specific strings

I need to fail one Jenkins pipeline stage when one file contains 'errors'
I do not know how to return an error from bash to Jenkins
stage('check if file continas error and exit if true') {
steps {
sh "grep 'error' filetocheck.txt"
}
}
}
reference Is it possible to capture the stdout from the sh DSL command in the pipeline
This worked for me,
def runShell(String command){
def responseCode = sh returnStatus: true, script: "${command} &> tmp.txt"
def output = readFile(file: "tmp.txt")
return (output != "")
}
pipeline {
agent any
stages {
stage('check shellcheck') {
steps {
script {
if (runShell('grep \'error\' file_to_parse.txt')) {
sh "exit 1"
}
}
}
}
}
}
you can try using String.count(charSequence) where String could be a file or string.
def file = 'path/to/file.txt'
if ( file.count('error') > 0 )
return stageResultMap.didB2Succeed = false

How to return environment values in jenkins declarative pipeline to a file?

I have a Jenkinsfile as below and
i am passing environment variables per stage,
want to create a docker.env file using these environment variables,
so i can use this docker.env file as part of my docker run 'docker run -d --env-file=docker.env java' per stage
looking for a <command_to_copy_all_values_under_'environment'_to_file_'docker.env'> ???
Jenkinsfile:
pipeline {
agent any
stages {
stage('Staging') {
environment {
KEY1_1=VALUE1_1
KEY1_2=VALUE1_2
KEY2_1=VALUE2_1
KEY2_2=VALUE2_2
}
steps {
timestamps() {
deleteDir()
sh '''
<command_to_copy_all_values_under_above_'environment'_to_file_'docker.env'>
docker run -d --env-file=docker.env java
'''
}
}
}
stage('Production') {
when {
branch 'release'
}
environment {
KEY1_1=VALUE1_1
KEY1_2=VALUE1_2
KEY2_1=VALUE2_1
KEY2_2=VALUE2_2
}
steps {
timestamps() {
timeout(time: 30, unit: 'MINUTES') {
input 'Ready to deploy to PRODUCTION, click PROCEED or ABORT ?'
}
deleteDir()
sh '''
<command_to_copy_all_values_under_above_'environment'_to_file_'docker.env'>
docker run -d --env-file=docker.env java
'''
}
}
}
}
tools {
maven 'apache_maven_352'
}
environment {
KEY1=VALUE1
KEY2=VALUE2
KEY3=VALUE3
KEY4=VALUE4
}
}
Here's solution with AWK:
awk -v B1="block-2" -v B2="block-Y" '/^[^ \t]/ { main=$1; next } main==B1 && $1==B2 { fnd=1; next } $1=="}" { fnd=0 } fnd && $0~/=/ { gsub(/^[ \t]+/,""); print $0 }' YOURFILE
Output:
key2_1=value2_1
key2_2=value2_2

Resources