When statement inside function called by Jenkins pipeline - jenkins

This question was migrated from Super User because it can be answered on Stack Overflow.
Migrated 28 days ago.
Is it possible to use a when statement inside of a function in a jenkinsfile?
My issue is the following: I created a deployment script using parallel that will perform it using a list of servers that are pre-configured (simple array) where I iterate over them to do the job. There is a parameter that is set when starting the build that will define which servers it should update, and here is the issue. I can add an if statement and it will work but, when checking blue ocean, all of the servers are green with 30ms, meaning that it didnt update as I wanted, not white as it was skipped when using when function.
Example below
def deployEnvironment(env) {
defineEnvironment()
defineAgent('build')
deploy(env)
}
If I try adding a when statement I get the message saying that the when statement is not within the steps accepted commands, even if I add it outside of the steps (or anywhere)
when {
expression { (someValidation())}
}
Is it even possible?

Related

Skip Jenkins Stage if its last excution was successfull

I am looking for way to speed up our Build-Pipeline.
The biggest impact would be to do certain things only if they have not been done.
So basically, I have already parameterized some optional stages which works fine, but there are some things I'd like to skip if there was a execution before which was successfull.
I have searched the docs, especially the section ref. when but the was nothing that did the job.
So the question is: Is there something I can do in a declarative pipeline to always skip a stage, except when
It has never been run successfully before
The last time it ran was not successful (eg. if I allow for its execution to be forced by passing a parameter)
I though about using the Build Number (eg only run it on the first execution of the pipeline), but this does't cut it for 2 reasons
I'm using milestones to prevent multiple executions of the pipe for a given branch/PR
If the first run fails, it would never be tried again
Oh, and I also thought about putting all of the logic in post -> regression and forcing the stage to fail on the first pipeline run, but this doesn't seem to be a good idea either.
One option ,although not ideal for large scale, can be to store the diffrent states as Global Environment Variables. (Manage Jenkins -> Configure System -> Global properties -> Environment variables).
These parameters are available for all jobs and can store parameters in a 'server wide' scope.
You can then update or set them via code using the following groovy method:
#NonCPS
def updateGlobalEnvVariable(String name, String value) {
def globalNodeProperties = Jenkins.getInstance().getGlobalNodeProperties()
def envVarsNodePropertyList = globalNodeProperties.getAll(hudson.slaves.EnvironmentVariablesNodeProperty.class)
if (envVarsNodePropertyList == null || envVarsNodePropertyList.size() == 0) {
def envVarsNodePropertyClass = this.class.classLoader.loadClass('hudson.slaves.EnvironmentVariablesNodeProperty')
globalNodeProperties.add(envVarsNodePropertyClass.newInstance())
}
envVarsNodePropertyList.get(0).getEnvVars().put(name, value)
}
This function will create the parameter if it does not exists or update its value in case it already exists. Also this function should better be placed in a Shared Library from which it will be available for all pipelines.
A nice advantage for this technique is that you can always 'reset' the different stages from the configuration page, However if you need to store multiple stages it can overflow the configuration page with a bit too much information.
Maybe you could use custom shared-workspace and then create/store some state file or something that could be used by your next executions like lastexecfailed.state and then try to locate the file on the shared workspace at the beginning of your execution.

Jenkinsfile: Define and assign values to several variables at once seems not to be implemented

I am using Jenkins 2.6 on Red Hat Linux. I want to use the following in my Jenkinsfile, but when I try, Jenkins complains bitterly. (It seems only to dislike the syntax on left-hand side of the = operator.):
def (a, b) = [6, 7]
It doesn't like Multiple Assignments it seems, yet Groovy 1.6 and later apparently support them, as per this post:
http://mrhaki.blogspot.co.uk/2009/09/groovy-goodness-multiple-assignments.html
I want to do this so that when I call a method that returns [6, 7] I can call it like this:
def (a, b) = mymethod()
def mymethod()
{
return [6, 7]
}
Can anyone tell me whether this should work in Jenkins and if so in which version of Jenkins? Or is it an unsupported feature? Or a bug?
Thanks
As explained here, Pipeline "scripts" are not simple Groovy scripts, they are heavily transformed before running, some parts on master, some parts on slaves, with their state (variable values) serialized and passed to the next step. As such, every Groovy feature is not supported.
I wish it was made more clear in Jenkins docs & presentations (that's why I find myself repeating the paragraph above... there is much confusion about this). Pipeline is so simple it seems magic... well, it kinda is ;)
It seems multiple assignments are not supported indeed. I only found this reference to confirm it: this example of a commit where the author changes his code from multiple assignments to simple ones because of that limitation.
Probably a good idea to ask for it on the mailing list as suggested by #rjohnston.
It should be available (and indeed it works from the Script Console) however it looks like whatever is necessary to make it work from a pipeline script hasn't been done.
The dev mailing list (https://groups.google.com/forum/#!forum/jenkinsci-dev) may be able to tell you if this is a bug or just an unsupported feature!

Creating conditional flows using Jenkin's Build Flow Plugin

We are using Jenkins for automated mobile device testing. However, sometimes the devices cannot be connected to and time is wasted running useless tests. To remedy this, we have instituted a connection check that only runs the test flow if a simple test can pass first.
Currently, this set up requires us to use 2 VMs, one to run the test and one to build the first and then wait around until its done to run the condition (we can't downstream for other reasons).
This is a pretty big resource hog, so I wanted to change the condition handling to the jenkins flow using the Build-Flow Plugin (https://wiki.jenkins-ci.org/display/JENKINS/Build+Flow+Plugin).
Does the plug-in handle conditionals as below? If so, what would be the correct syntax for the conditional statement?
build("Connection-check")
if(Connection-check.lastBuild == Pass) //Guessed Pseudo-expression
{build("Rest-of-Tests")}
Okay, so in the end I constructed a secondary flow that ran first, and only kicked off the main flow if a connection could be made using the standard conditional tools.
A little bit less compact than I would have liked, but at the least it was clear as to what it did.
Try this condition:
if(hudson.model.Hudson.instance.getItem("Connection-check").getLastBuild().result == hudson.model.Result.SUCCESS)
{
build("Rest-of-Tests")
}
I think you can use also something like that:
import hudson.model.*
def connCheck = build("Connection-check") //Returns hudson.model.AbstractBuild
if(connCheck.result == Result.SUCCESS) {
...
}

One of configurations from matrix gets cancelled every time

I have two projects and with dependencies so that project A is started, it updates files from git and then runs a multi-configuration project B, which:
has three axes: "foo", "bar" and "baz" with 11 x 4 x 2 items
I'm going to call the values like fooN for item N from axis foo, etc.
has a configuration filter, ruling out the last axis by running only when
baz=="baz1" (maybe in a later phase we'll want to run also tests with baz2
for baz)
runs a shell script that only cds and calls python interpreter with a script
cd /path/to/scripts
python test_${bar}.py
So when the project is run, I expect 44 configurations to be tested. But only 43 are.
It's always the same configuration (which happens to be the last one triggered, as Jenkins seems to remember the order(?)) that does never run at all:
in the final matrix looks as a gray dot with "Disabled" tooltip
in Console output, after saying "Triggering bazN,barN,fooN" for all 44 combinations,
then "bazN,barN,fooN completed with result SUCCESS" for all except the last one, but
the last one seems to be always cancelled/aborted:
baz1,bar7,foo3 appears to be cancelled
baz1,bar7,foo3 completed with result ABORTED
Console output for the single combination is not available---it looks like it never
has been built
Jenkins log does not show anything interesting about "baz1,bar7,foo3"
What does this mean? Any other pointers how to troubleshoot this?
Edit: I tried adding a "HTTP ping" script to the repo and called it from above script,
just before the python test_${bar}.py part. Which proved that for the affected
configuration, Jenkins does not even run those lines.
Without knowing how you got here to begin with (probably a bug):
Append configure to the URL of the disabled configuration, and in the resulting form, uncheck Disabled and Save.
Not really an answer, but as a workaround to the problem, cloning whole project to a new one helped: with the new project, all configurations ran normally.
This is a solved Jenkins issue:
https://issues.jenkins-ci.org/browse/JENKINS-19179
By the Matrix Project plug-in, version 1.4:
https://wiki.jenkins-ci.org/display/JENKINS/Matrix+Project+Plugin

How do I "map" certain return value of a script to "yellow" status in Jenkins?

In Jenkins there is a possibility to create free project which can contain a script execution. The build fails (becomes red) when the return level of the script is not 0.
Is there a possibility to make it "yellow"?
(Yellow usually indicates successful build with failed tests)
The system runs on Linux.
Give the Log Parser Plugin a try. That should do the trick for you.
One slightly hacky way do do it, is to alter the job to publish test results and supply fake results.
I've got a job that is publishing the test results from a file called "results.xml". The last step in my build script checks the return value of the build, copies eihter "results-good.xml" or "results-unstable.xml" to "results.xml" and then returns a zero.
Thus if the script fails on one of the early steps, the build is red. But if the build succeeds its green or yellow based on the return code it would have retunred without this hack.

Resources