I have a groovy script inside my pipeline that load some text from an json file. Now I want to combine this loaded text with existing environment variable, but it will not fill the placeholder. What I do:
json
{
"resource": {
"SERVICE_API_URL":"http://my-service-svc.${KUBERNETES_HOST}:5000"
}
}
script {
env.KUBERNETES_HOST = "myjenkins"
env.JSONSTRING = readFile(file: 'pipeline/pipeline.config')
def propsen = readJSON text: "${env.JSONSTRING}"
env.test = propsen.resource.SERVICE_API_URL
echo "${test}"
}
I hoped that this will echo "http://my-service-svc.myjenkins:5000"
but it still echo "http://my-service-svc.${KUBERNETES_HOST}:5000"
So is there a trick how to do fill this "nested" variable in a dynamic loaded variable?
Try adding env to your variable in *.json file, like this:
{
"resource": {
"SERVICE_API_URL":"http://my-service-svc.${env.KUBERNETES_HOST}:5000"
}
}
Related
It is possible to make the Jenkins groovy interpreter interpret the content of a variable until no more variable names are found?
def final_string = "demo"
def embedded_var = "$final_string"
node {
stage('Stage demo error') {
echo "$embedded_var" // will display $final_string
}
}
I have defined an environment(global) variable in jenkins via configuration as
REPORT = "Test, ${CycleNumber},${JOB_NAME}"
I have 1 parameter defined in my pipeline called Cycle which has values new & update. Based on this cycle value CycleNumber should be updated and I tried it via groovy using script block in my pipeline as below
if(Cycle == "New")
{
CycleNumber = "12345"
}
else if (Cycle == "Update")
{
CycleNumber = "7890"
}
after this update if I do echo "${env.REPORT}" I get the value as "Test,,TestJob" where in the CycleNumber variable is not updated. Could you please let me know if there is a way to update this CycleNumber field ?
Don't rely on Groovy's String interpolation to replace the CycleNumber. You can have your own placeholder(e.g: _CYCLE_NUMBER_) in the environment variable which you can replace later in your flow. Take a look at the following example.
pipeline {
agent any
stages {
stage("Test") {
environment {
REPORT = "Test, _CYCLE_NUMBER_,${JOB_NAME}"
}
steps {
script {
def Cycle = 'New'
def CycleNumber = 'none'
if(Cycle == "New"){
CycleNumber = "12345"
} else if (Cycle == "Update") {
CycleNumber = "7890"
}
def newReport = "$REPORT".replace('_CYCLE_NUMBER_', CycleNumber)
echo "$newReport"
}
}
}
}
}
Also once you set the newReport variable, make sure you use the same variable. if you do "${env.REPORT}" you will always get the original value assigned the tne environment variable.
Here is an answer with a workaround here: Updating environment global variable in Jenkins pipeline from the stage level - is it possible?
TLDR:
You can't override a global environment variable that has been declared in environment(global), however you can use the withEnv() function to wrap your script block in your pipeline to reference the updated value, eg:
withEnv(['REPORT=...']) {
// do something with updated env.REPORT
}
I need to assign the BUILD_NUMBER environment variable to user defined variable.
I tried various options like def, environment block and did not work.
I want to assign variable like def a = ${BUILD_NUMBER} and your input to work this code part will be highly appreciated
pipeline{
agent any
environment {
jenkinbuild=echoRestartedInfo()
}
stages {
stage('Stage 1') {
steps {
echo "stage 1"
echo "${BUILD_NUMBER}"
echoRestartedInfo()
echo "${jenkinbuild}"
}
}
}
}
def echoRestartedInfo() {
def a = ${BUILD_NUMBER}
return a
}
The output - echo "${jenkinbuild}"
is expected same as echo "${BUILD_NUMBER}" but this shows multiple compilation error .
I do not want to code this with script{} as it should be added to each stage
Check the following.
def echoRestartedInfo() {
return env.BUILD_NUMBER
}
Or
def echoRestartedInfo() {
return "${BUILD_NUMBER}"
}
I just tried to optimize your function. You can simply replace the return with an assignment if you want to assign to a variable.
def a = env.BUILD_NUMBER
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
I'm trying to dynamically set environment variables in the jenkins pipeline script.
I'm using a combination of .groovy and .jenkinsfile scripts to generate the stage{} definitions for a pipeline as DRY as possible.
I have a method below:
def generateStage(nameOfTestSet, pathToTestSet, machineLabel, envVarName, envVarValue)
{
echo "Generating stage for ${nameOfTestSet} on ${machineLabel}"
return node("${machineLabel}") {
stage(nameOfTestSet)
{
/////// Area of interest ////////////
environment {
"${envVarName} = ${envVarValue}"
}
/////////////////////////////////////
try {
echo "Would run: "+pathToTestSet
} finally {
echo "Archive results here"
}
}
}
}
There's some wrapper code running this, but abstracting away we'd have the caller essentially use:
generateStage("SimpleTestSuite", "path.to.test", "MachineA", "SOME_ENV_VAR", "ENV_VALUE")
Where the last two parameters are the environment name (SOME_ENV_VAR) and the value (ENV_VALUE)
The equivalent declarative code would be:
stage("SimpleTestSuite")
{
agent {
label "MachineA"
}
environment = {
SOME_ENV_VAR = ENV_VALUE
}
steps {
echo "Would run" + "path.to.test"
}
post {
always {
echo "Archive results"
}
}
}
However, when running this script, the environment syntax in first code block doesn't seem to affect the actual execution at all. If I echo the ${SOME_ENV_VAR} (or even echo ${envVarName} in case it took this variable name as the actual environment value) they both return null.
I'm wondering what's the best way to make this environment{} section as DRY / dynamic as possible?
I would prefer it if there's an extendable solution that can take in a list of environmentName=Value pairs, as this would be more general case.
Note: I have tried the withEnv[] solution for scripted pipelines, however this seems to have the same issue.
I figured out the solution to this.
It is to use the withEnv([]) step.
def generateStage(nameOfTestSet, pathToTestSet, machineLabel, listOfEnvVarDeclarations=[])
{
echo "Generating stage for ${nameOfTestSet} on ${machineLabel}"
return node("${machineLabel}") {
stage(nameOfTestSet)
{
withEnv(listOfEnvVarDeclarations) {
try {
echo "Would run: "+pathToTestSet
} finally {
echo "Archive results here"
}
}
}
}
}
And the caller method would be:
generateStage("SimpleTestSuite", "path.to.test", "MachineA", ["SOME_ENV_VAR=\"ENV_VALUE\""])
Since the withEnv([]) step can take in multiple environment variables, we can also do:
generateStage("SimpleTestSuite", "path.to.test", "MachineA", ["SOME_ENV_VAR=\"ENV_VALUE\"", "SECOND_VAR=\"SECOND_VAL\""])
And this would be valid and should work.