Is it possible to set a label instead of a name for nodes Groovy? We want to define labels outside the script to easily access them from the Jenkins Dashboard.
Idea:
Instead of:
Groovy Script
node('Slave_1 || Slave_2'){ echo 'Hello world' }
We want something like this:
Pipeline configuration
Node Label Name: slaveGroup
Node Label Value: Slave_1 || Slave_2
Groovy Script
node(slaveGroup){echo 'Hello world'}
Or is it possible to use the labels you can set in slave configuration directly in the Groovy script?
Just found out that the Pipline Syntax (Generator) gives this option:
Valid Operators
The following operators are supported, in the order of precedence.
(expr)
parenthesis
!expr
negation
expr&&expr
and
expr||expr
or
a -> b
"implies" operator. Equivalent to !a|b. For example, windows->x64
could be thought of as "if run on a Windows slave, that slave must be
64bit." It still allows Jenkins to run this build on linux.
a <-> b
"if and only if" operator. Equivalent to a&&b || !a&&!b. For example,
windows<->sfbay could be thought of as "if run on a Windows slave,
that slave must be in the SF bay area, but if not on Windows, it must
not be in the bay area."
All operators are left-associative (i.e., a->b->c <-> (a->b)->c ) An
expression can contain whitespace for better readability, and it'll be
ignored.
Label names or slave names can be quoted if they contain unsafe
characters. For example, "jenkins-solaris (Solaris)" || "Windows 2008"
More in the documentation.
Related
I have a pipeline job which runs a sequence of jobs (Eg; setup >> run test >> clean). I want this sequence to run for 100 different tool with different parameter for each tool. Parameterising is done. So I can pass different parameter.
I am passing one parameter to pipeline as tool list as a string parameter which will have the tools separated with comma (Eg; tool1, tool2, tool3)
Now I want to change the pipeline to run the same sequence(setup >> run test >> clean) in all the tools with tool name passed to one of the job as parameter.
I was thinking I will take this parameter value and spit it with comma and get each tool name and have a for loop around the sequence.
I could get having forloop part and it is working for a multiple run.
for (int i = 0; i < 2; ++i) {
stage('Setup') {
build job: 'setup', parameters: [string(name: 'tool', value:'<tool>')]
}
stage('Build') {
build 'Build Job'
}
}
But I am not getting how can we split the parameter and give one one to each iteration of forloop in DSL. Can anybody help on this?
Parameters in jenkins are available under the "param" variable. And you can split a string into an array of strings using the split () function. After that, if you want to loop over all strings, you can use a for loop, iterating through the array, something like:
def tools = params.tool.split (',') // default separator is blanks
for (String part : tools)
{
println (part)
}
There are different ways to iterate, this seems very intuitive to me. Notice that using the specific separator makes blanks after the comma part of the strings. If needed, you can use the trim () function to remove it.
Someone ask about how to create an agent and it create a slave node (here), and I don't know if it's true or no :
agent {
label 'my-defined-label'
}
and
agent {
node {
label 'my-defined-label'
customWorkspace '/some/other/path'
}
}
So 'my-defined-label' is just slave name?
Thanks for the answers
It can match an exact node name, a label, any other supported label expression. For example, java8 && linux, (docker || java) && !windows , and corp-agent-node-01-name are all valid label syntax.
The documentation is clear about how the built in syntax works:
Allocates an executor on a node (typically a slave) and runs further code in the context of a workspace on that slave.
label - Computer name, label name, or any other label expression like linux && 64bit to restrict where this step builds. May be left blank, in which case any available executor is taken.
Valid Operators
The following operators are supported, in the order of precedence.
(expr) - parenthesis
!expr - negation
expr&&expr - and
expr||expr - or
a -> b - "implies" operator. Equivalent to !a|b. For example, windows->x64 could be thought of as "if run on a Windows slave, that slave must be 64bit." *It still allows Jenkins to run this build on linux.
a <-> b - "if and only if" operator. Equivalent to a&&b || !a&&!b. For example, windows<->sfbay could be thought of as "if run on a Windows slave, that slave must be in the SF bay area, but if not on Windows, it must not be in the bay area."
All operators are left-associative (i.e., a->b->c <-> (a->b)->c ) An expression can contain whitespace for better readability, and it'll be ignored.
Label names or slave names can be quoted if they contain unsafe characters. For example, "jenkins-solaris (Solaris)" || "Windows 2008"
I inject environmental variable from a file myprop.property that has the contents:
var1=y
var2=y
The build steps:
1. Inject environment variables:
Property File Path:${JENKINS_HOME}/myprop.propertie
Execute Windows batch command (to verify variable injected successully)
echo var1 = %var1% echo var2 = %var2%
Condition steps (multiple)
Run?: Boolean condition
Token: ${ENV,var="var1"}||${ENV,var="var2"}
Steps to run if condition is met: echo Yes, works!
Run the build, the condition in step 3 never met while step 2 display the correct values of the variables.
I have tried the conditions and operators:
var1=y, var2=y: ${ENV,var="var1"}||${ENV,var="var2"}
var1=y, var2=y: ${ENV,var="var1"}|${ENV,var="var2"}
var1=y, var2=n: ${ENV,var="var1"}||${ENV,var="var2"}
var1=y, var2=n: ${ENV,var="var1"}|${ENV,var="var2"}
Uppercase or lower case of the values do not make any difference. I am running jenkins 1.641 on windows 7 pro.
If I use only one e.g. ${ENV,var="var1"} in the token field, it works as expected.
Try this instead, It worked for me, we need to mention Boolean Condition with Token mentioned in the image.
This works, change step 3 to:
Run?: Or
Boolean condition
Token: ${ENV,var="var1"}
Or
Boolean condition
Token: ${ENV,var="var2"}
Never
these are actually three conditions. the execution asserts the first condition first, if it's met, stop checking; if not met, asserts the second; and so on until the last condition that is Never, meaning if no condition is met, stop executing the step.
I see my post attracted lots interests. Here are what I eventually worked around.
Use Regular expression match seems to be more readable than using Boolean Condition.
If the logic is an "OR",
? = Regular expression match
expression = ${ENV,var="var1"}|${ENV,var="var2"}
Label = Y
Note that the logic operator is a single '|', not double '||'.
if the logic is an "AND",
? = Regular expression match
expression = ${ENV,var="var1"}${ENV,var="var2"}
Label = YY
The expression is just concatenation of the two variables, and the Label is so as well.
I want my Domain specific language (DSL) to accept command-line arguments as variables like in bash scripts. For example: A user might issue a command runMyDSL myDslFile.dsl -args 10 15 or runMyDSL myDslFile.dsl -nvargs arg1=10 arg2=15. I would like to capture these values into variables $1, $2 for first command or $arg1, $arg2 for second command. These variables can then be treated as any other read-only variables in my DSL:
val someVariable = $1
Since I am new to xtext/parser field, I am looking for best practices people follow for dealing with this situation. For simplicity, let's assume, I am only working on simplified DSL that does addition (based on Expression Language described in http://blog.efftinge.de/2010/08/parsing-expressions-with-xtext.html):
Expression : Variable '+' Variable;
Variable: ('val' ID '=' INT) | CommandLineVariable;
CommandLineVariable: ??;
My first idea for that would be the following:
1.) parse the DSL file and get access to the AST, store the refence in any locally definded variable of the corresponding EClass.
2.) Use the 'MyDslFactory' class to create a new 'Variable' instance, set a value, given by the command line and put it somewhere into the AST.
To do that you should define attribute names in you 'Variable' Parser Rule:
Variable: 'val' name=ID '=' value=INT;
'Variable' creation would look like this (more or less):
Variable newVar = MyDslFactory.eINSTANCE.createVariable();
newVar.setName(args[2].split("=")[0]);
newVar.setValue(new Integer(args[2].split("=")[1]));
Then you put it into the AST and with the modified AST you could either create a temporary DSL file which is then processed as before or you process the AST directly.
Is it possible to cancel or skip a job in Jenkins due to special commit-message patterns? I thought the option "Excluded Commit comments" in the job configuration does this for me out of the box, like mentioned here. But no matter which regular expression i write in this field, the build is performed nevertheless.
For example:
I want to perform the build job only if the commit message includes the expression "release". So i write the regular expression [^(?:release)] in the Excluded Commit comments field. I thought if i commit a revision with, for example "test commit" the build-job does not perform, right? Is this the right way to do when not using a post-commit hook?
Jenkins Git plugin exposes you the environment variable GIT_COMMIT which of course, contains the current git commit hash.
Use [Jenkins Conditional Step] and build a step which execute the following bash shell:
echo "==========================="
if [ "git show $GIT_COMMIT | grep "your-pattern-here" == false ] ; then
echo "pattern failed";
exit 1
else
echo "ok"
fi
echo "==========================="
And mark that if the shell fails, fail the build.
Late reply but may help some one in future,
There is a plugin to skip build depending on git commit message, just include a [ci-skip] in the commit message junkin will skip the build
jenkins-ci-skip-plugin
TL;DR
To trigger builds only for commits with "release" word (case-insensitive) set this in the "Excluded Commit comments" field in job configuration:
(?i)(?s)(?!.*\brelease\b.*)^.*$
Better still, use a trigger phrase which is unlikely to be added to a commit message accidentally. For example, use "[ci build]":
(?i)(?s)(?!.*\[ci build\].*)^.*$
How does this work?
(?i) tells regex do do case-insensitive match. This is optional, but useful if you want to match "Release" and "RELEASE" as well as "release".
(?s) makes dot to match line-ends (aka dotall option), so that we look for matches within the entire commit message. By default dot doesn't match line-ends, so if there is no "release" keyword on one of the lines in the commit message, the pattern would match on that line, and commit would be incorrectly ignored by Jenkins. With dotall, we look at the entire commit message, ignoring any line ends.
(?!.*\brelease\b.*) - negative look-ahead pattern. Any match is discarded if this pattern is found within it. In this pattern:
.* matches anything before our trigger phrase and after it. We need this because of the way java regex matching works (quote from the tutorial):
myString.matches("regex") returns true or false depending whether the string can be matched entirely by the regular expression. It is important to remember that String.matches() only returns true if the entire string can be matched. In other words: "regex" is applied as if you had written "^regex$" with start and end of string anchors. This is different from most other regex libraries, where the "quick match test" method returns true if the regex can be matched anywhere in the string. If myString is abc then myString.matches("bc") returns false. bc matches abc, but ^bc$ (which is really being used here) does not.
\b makes sure that there is a word boundary before and after the keyword, as you probably don't want to match "unreleased" etc.
^.*$ is the actual matching pattern we are looking for. Note that ^ and $ match start of the string and end of the string, not the start/end of lines within that string. This is default behavior for java regex, unless multi-line mode is enabled. In other words, this pattern matches the entire commit message, because dotall mode was enabled by (?s) and dot matches newlines.
So matching algorithm would match the entire commit message, and then discard it or not depending on whether it finds negative look-ahead pattern anywhere in it.
Why your expression didn't work?
There were two problems with your suggested regex expression. First, you used incorrect regex syntax for excluding a pattern. Second, you didn't tell what your pattern should include, only what it should exclude. Therefore it would never match anything even if you used correct syntax. And because it doesn't match anything, then nothing is excluded from triggering jobs, i.e. any commits would trigger.
References
If you need more information, look for java.util.regex package which is used by Jenkins uses for matching. I used this online java regex tester to test my expressions. I've also found a nice tutorial - learned about (?m), (?s) and (?i) there.