I have a parameterized build like below:
then i've create a groovy script to create a variable URL_TOMCAT where its value depends on the TARGET_TOMCAT parameter:
Even after this update i got the same error
import hudson.model.*
def target = build.buildVariableResolver.resolve("TARGET_TOMCAT")
def URL_TOMCAT = ""
switch(target ) {
case "tomcat1": URL_TOMCAT= "http://localhost:8080/manager/text"
break
case "tomcat2": URL_TOMCAT = "http://localhost:8089/manager/text"
break
}
Then i want to get The URL_TOMCAT value and adjust the maven build step as shown:
But i got this error :
Has any on an idea how to fix this error?
In your groovy script you need to make an API call to get the value of the parameter from Jenkins into your workspace.
Import hudson.model
def targetTomcat = build.buildVariableResolver.resolve("TARGET_TOMCAT")
def URL_TOMCAT = ""
switch(targetTomcat) {
case "tomcat1": URL_TOMCAT = "http://localhost:8080/manager/text"
break
case "tomcat2": URL_TOMCAT = "http://localhost:8089/manager/text"
break
}
I want to point out that the URL_TOMCAT variable won't be available to any other buildsteps, it's scoped to just the groovy build step. If you want to expose your URL_TOMCAT variable to the rest of the build you'll need to expose it to the build environment somehow. I normally do this by writing the value to a file as a key value pair and using the EnvInject Plugin
You can write it to a file in groovy like so:
def workspace = build.buildVariableResolver.resolve("WORKSPACE")
new File("${workspace}\\Environment.Variables").write("URL_TOMCAT=${URL_TOMCAT}")
If you don't want to write it to the jobs workspace you can skip grabbing that value and just code a specific path.
After your groovy build step add an Envinject build step and enter the path to the file containing the key value pair in the Properties File Path field. You should be able to reference URL_TOMCAT like any other environment variable in the rest of the build. Continuing with the about path I would use ${WORKSPACE}\Environment.Variables as the path.
Related
I'm creating a new pipeline job, before execute detail bat files, there are lots of variable to define.
node('BuildMachine')
{
env.ReleaseNumber='1.00.00'
env.BuildType='Test'
env.Language='ENU'
...
Stage('Build')
{
bat '''
call build.bat %ReleaseNumber%_%BuildType%_%BUILD_NUMBER%
'''
}
}
Can I save these global variable to a config file, store in git repository and read it?
Can these variable still work in bat?
EnvInject Plugin aka (Environment Injector Plugin) gives you several options to set and use environment variables in Jenkins job.
It will write the variables to a file which can be loaded later to get the variables, but I don't think the variables will directly work in bat.
If you have to define the variables in every build, you could (because the Jenkinsfile is actually just Groovy) define variables and use them in the call as command line arguments:
node('BuildMachine') {
def releaseNumber='1.00.00'
def buildType='Test'
def language='ENU'
Stage('Build')
{
bat "call build.bat ${releaseNumber}_${buildType}_%BUILD_NUMBER%"
}
}
I assume that BUILD_NUMBER is a environment variable set before starting the build job. Otherwise you could do it like the others. Note that the double quotation marks instead of the single quotation marks are necessary for that to work.
Another option is that you define a < key > = < value > file and then you can do:
readFile "<your config file>"
configData = file.split("\n")
configData.each {
lineData = it.split("=")
switch(lineData[0].toLowerCase().trim()){
case "<key 1>": <varName 1> = lineData[1].trim(); break;
case "<key 2>": <varName 2> = lineData[1].trim(); break;
case "<key 3>": <varName 3> = lineData[1].trim(); break;
....
}
}
And then use the varName to call the bat as you mentioned
The advantage with this code is that you don't depend on the order of the contents of the config file
I have an Jenkins Freestyle job with an system groovy script in the Build area. After executing the script I want to trigger a pipeline job. The pipeline job needs a variable who gets defined inside my groovy scipt.
if(condition1){
var = 'String1'
}else{
var = 'String2'
}
But I need to get acces to my variable var at the "post-build-action" step at the "Trigger parameterized build on other projects" option to trigger my pipeline with var as parameter. Is this possible?
Yes, it is possible. You can simply write your variables as key-value pairs in a property file and load it in your post-build-action by specifying Parameters from properties file.
You can save your property file like this
def fw = new OutputStreamWriter(new FileOutputStream("params.properties",true), 'UTF-8')
def props = new Properties()
props.setProperty('TESTPARAM', var)
props.store(fileWriter, null)
fw.close()
I solved my problem the following way:
Before building I define a parameter to use the parameterized trigger plugin. Inside my system groovy script I override it with
def newMailParameter = new StringParameterValue('MAIL_PARAM', mailsFromWS)
build.replaceAction(new ParametersAction(newMailParameter))
Now I can trigger the next job and use my parameter MAIL_PARAM inside of it.
Is there a way to change project variable values in Jenkins automatically when build is done?
In my case i got a variable VERSION, default value is 1. And i need to increment this default value every build done. Assuming build stars by cron in this case. Any plugins can help me?
Now i have something like this: My build steps.
It is a single working way to get project variable in my groovy script that i found. Now how can i set new value for variable?
I read some similar question on SO, but didn't found a working way for me.
P.S. I can't use $BUILD_NUMBER var, because i need a possibility to set VERSION manually when i start build.
First, of all, install the plugins Global Variable String Parameter Plugin and Groovy Postbuild Plugin. Under Manage Jenkins -> Configure System you should now have a part, called Global Properties. There you add a new variable. In my tests, I called it SOME_VER.
At your job, you now add a Groovy postbuild part with this code adjusted to your variable:
import jenkins.*;
import jenkins.model.*;
import hudson.*;
import hudson.model.*;
import java.lang.*;
instance = Jenkins.getInstance();
globalNodeProperties = instance.getGlobalNodeProperties();
envVarsNodePropertyList = globalNodeProperties.getAll(hudson.slaves.EnvironmentVariablesNodeProperty.class);
envVars = null
if (envVarsNodePropertyList != null && envVarsNodePropertyList.size() > 0)
{
envVars = envVarsNodePropertyList.get(0).getEnvVars()
String value = envVars.get("SOME_VER", "0")
int NEW_VER = Integer.parseInt(value)
NEW_VER = NEW_VER + 1
envVars.override("SOME_VER", NEW_VER.toString());
}
instance.save()
Parts of this code are taken from here. This code does nothing else than retrieving the value of the global variable, change it and save the new value of the variable.
I try to launch a job from a parametrized trigger and I would compute the name from a given variable.
Is it possible to set in field :
Build Triggers Projects to build
a value like this
${RELEASE}-MAIN-${PROJECT}-LOAD_START
?
Unfortunately, this isn't possible with the Build Triggers. I looked for a solution for this "higher order build job" that would allow you to create a dynamic build name with a one of the parameterized build plugins, but I couldn't find one.
However, using the Groovy Postbuild Plugin, you can do a lot of powerful things. Below is a script that can be modified to do what you want. In particular, notice that it gets environmental variables using build.buildVariables.get("MY_ENV_VAR"). The environmental variable TARGET_BUILD_JOB specifies the name of the build job to build. In your case, you would want to build TARGET_BUILD_JOB using these two environmental variables:
build.buildVariables.get("RELEASE")
build.buildVariables.get("PROJECT")
The script is commented so that if you're not familiar with Groovy, which is based off Java, it should hopefully make sense!
import hudson.model.*
import hudson.model.queue.*
import hudson.model.labels.*
import org.jvnet.jenkins.plugins.nodelabelparameter.*
def failBuild(msg)
{
throw new RuntimeException("[GROOVY] User message, exiting with error: " + msg)
}
// Get the current build job
def thr = Thread.currentThread()
def build = thr?.executable
// Get the parameters for the current build job
// For ?:, see "Elvis Operator" (http://groovy.codehaus.org/Operators#Operators-ElvisOperator)
def currentParameters = build.getAction(ParametersAction.class)?.getParameters() ?:
failBuild("There are no parameters to pass down.")
def nodeName = build.getBuiltOnStr()
def newParameters = new ArrayList(currentParameters); newParameters << new NodeParameterValue("param_NODE",
"Target node -- the node of the previous job", nodeName)
// Retrieve information about the target build job
def targetJobName = build.buildVariables.get("TARGET_BUILD_JOB")
def targetJobObject = Hudson.instance.getItem(targetJobName) ?:
failBuild("Could not find a build job with the name $targetJobName. (Are you sure the spelling is correct?)")
println("$targetJobObject, $targetJobName")
def buildNumber = targetJobObject.getNextBuildNumber()
// Add information about downstream job to log
def jobUrl = targetJobObject.getAbsoluteUrl()
println("Starting downstream job $targetJobName ($jobUrl)" + "\n")
println("======= DOWNSTREAM PARAMETERS =======")
println("$newParameters")
// Start the downstream build job if this build job was successful
boolean targetBuildQueued = targetJobObject.scheduleBuild(5,
new Cause.UpstreamCause(build),
new ParametersAction(newParameters)
);
if (targetBuildQueued)
{
println("Build started successfully")
println("Console (wait a few seconds before clicking): $jobUrl/$buildNumber/console")
}
else
failBuild("Could not start target build job")
I need to pass the username of the requester of a build down to the script that is actually doing the work. Looking at the console output for a particular build, the first line is always "Started by user foo," so Jenkins is clearly keeping track of who triggered the build. So it should be possible to pass that information down to the job. The question is, how?
user30997
Please check out Jenkins Build User Vars plugin, it does what you need:
It is used to set following user build variables:
BUILD_USER – full name of user started build,
BUILD_USER_FIRST_NAME – first name of user started build,
BUILD_USER_LAST_NAME – last name of user started build,
BUILD_USER_ID – id of user started build.
The username isn't put in an easy-to-fetch environment variable, but you can get it using the xml (or json or python) api - as soon as you start a build, http://[jenkins-server]/job/[job-name]/[build-number]/api/xml is populated with details:
<freeStyleBuild>
<action>
<cause>
<shortDescription>Started by user foobar</shortDescription>
<userName>foobar</userName>
</cause>
</action>
<building>true</building>
[...]
I tried to use Jenkins Build User Vars plugin and notify a HipChat room that a build was started by a certain user, but BUILD_USER variable was not available to HipChat plugin, possibly because HipChat action happened before Build User Vars plugin injects the variable.
So I installed pre-scm-buildstep plugin and added:
]
// Inject environment variables using Groovy
import hudson.model.*
def build = Thread.currentThread().executable
def userCause = build.getCause(hudson.model.Cause$UserIdCause)
def userName = userCause?.userId ?: 'Jenkins'
def envVars = ['BUILD_USER': userName]
for (item in envVars) {
build.addAction(new ParametersAction([
new StringParameterValue(item.key, item.value)
]))
}
In your Job add "Execute system Groovy script":
def yourUserName = build.causes[0].userId
I managed to get it (on Jenkins 2.58):
currentBuild.getRawBuild().getCauses()[0].getUserId()
Of course you need to set permissions in Jenkins to be able to call these methods.
It's not always the 0th Cause object you are looking for, e.g. it may be another one if you replay another user's build (did not test this).
import os
import jenkinsapi.build
import jenkinsapi.jenkins
#Required Environment variables example:
#JENKINS_URL=http://jenkinsserver/
#JOB_NAME=TEST_GT
#BUILD_NUMBER=8
jenkins_inst = None
def get_jenkins_inst():
if jenkins_inst == None:
jenkins_url = os.environ['JENKINS_URL']
print("Connect to jenkins " + jenkins_url)
jenkins_inst = jenkinsapi.jenkins.Jenkins(jenkins_url)
return jenkins_inst
def get_jenkins_job():
jenkins_inst = get_jenkins_inst()
jenkins_job_name = os.environ['JOB_NAME']
print("Get jenkins job " + jenkins_job_name)
return jenkins_inst.get_job(jenkins_job_name)
def get_jenkins_user():
jenkins_job = get_jenkins_job()
jenkins_buildno = int(os.environ['BUILD_NUMBER'])
print("Get jenkins job build " + str(jenkins_buildno))
cur_build = jenkins_job.get_build(jenkins_buildno)
return cur_build.get_actions()['causes'][0]['userId']