Jenkins conditional steps token logic operators - jenkins

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.

Related

Why we are unable to evaluate comprehension if we have defined it inside a rule body in OPA?

The following is my sample code: https://play.openpolicyagent.org/p/oyY1GOsYaf
Here when I try to evaluate names array, it is showing:
error occurred: 1:1: rego_unsafe_var_error: var names is unsafe
But when I define the same comprehension outside the allow rule definition : https://play.openpolicyagent.org/p/Xv0cF7FM8b, I am able to evaluate the selection
[
"smoke",
"dev"]
could someone help me to point out the difference and if I want to define the comprehention inside the rule is there any syntax I need to follow? Thanks in advance
Note: I am getting the final output as expected in both cases, only issue is with the names array evaluation.
The way the Rego Playground generates a query when evaluating a selection is much more simplistic than one might assume. A query will be generated from your selected text, without taking into account where in the document that text was selected. This means that even if you select a local variable inside a rule body, the query will simply contain that variable name (names, in your case); which will be perceived as a reference to a top-level variable in the document's body, even though a rule-local variable was selected. This is why your first sample returns an error, as there is no top-level variable names in the document; whereas the second sample does, and therefore succeeds.
You can test this quirk by selecting and evaluating the word hello on line 3 here: https://play.openpolicyagent.org/p/n5OPoFnlhx.
package play
# hello
hello {
m := input.message
m == "world"
}
Even though it's just part of a comment, it'll evaluate just as if you had selected the rule name on line 5.

How to handle parameters of pipeline job in DSL?

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.

foreach random no match

This is for code:
set source_failed = `cat mine.log`
set dest_failed = `cat their.log`
foreach t ($source_failed)
set isdiff = 0
set sflag = 0
foreach t2 ($dest_failed)
if ($t2 == $t) then
set sflag = 1
break
endif
end
...
end
Problem is that the inner foreach loop runs okay for first few 10 iterations. After that iteration, suddenly I got
foreach: no match
Moreover, I am iterating over the array of strings, not files. What is the reason behind this error?
The problem is (probably) that mine.log and/or their.log contain special globbing characters, such as * or ?. The shell will try to expand this to a file. There are no matches for this accidental pattern, and hence the error "no match".
The easiest way to prevent this behaviour is to add set noglob to the top. From tcsh(1):
noglob If set, Filename substitution and Directory stack substitution
(q.v.) are inhibited. This is most useful in shell scripts
which do not deal with filenames, or after a list of filenames
has been obtained and further expansions are not desirable.
You can re-enable this behaviour by using set glob.
Alternativly, you can use :q. From tcsh(1):
Unless enclosed in `"' or given the `:q' modifier the results of variable
substitution may eventually be command and filename substituted.
[..]
When the `:q' modifier is applied to a substitution the variable will expand
to multiple words with each word sepa rated by a blank and quoted to
prevent later command or filename sub stitution.
But you need to be very careful about quoting when you use the variable. In the below example, the echo command will fail if you don't add quotes (set noglob is much easier):
set source_failed = `cat source`
foreach t ($source_failed:q)
echo "$t"
end

Jenkins: avoid build due to commit message

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.

"do" in "do Application.Run(form)" sentence

What is the difference between
do Application.Run(form)
and, simply:
Application.Run(form) ?
What is the role of do keyword in the first sentence?
Whereas 'do' was a required keyword in many places in the language in some of the earlier releases, nowadays you rarely need 'do'. The remaining exceptions that I can think of are that 'do' is still part of loop syntax (e.g. "while e1 do e2") and if you want to put an assembly-level attribute or an attribute on the startup method, you can put the attribute before the explicit 'do' of a final code block in a module. Often times in F# samples you'll see
[<STAThread>]
do Application.Run(form)
as the last two lines of a file, and I think the 'do' is still required there in order to be able to attach the attribute on the line above it.
I think it's just a holdover - like how you can still CALL a sub or SET a variable instead of just doing those things directly, as in:
SET varname = 5
CALL mysub()
Versus just:
varname = 5
mysub()
In other words, I don't think it matters, and the compiler just discards it.

Resources