The Jenkins Job DSL Plugin documentation describes the following:
removeAction - "action to be taken for job that have been removed from DSL scripts"
removeViewAction - "action to be taken for views that have been removed from DSL scripts"
However the pipeline documentation for Job DSL lists slightly different names:
removedJobAction (extra d and Job)
removedViewAction (extra d)
They seem to have the same effect so why are there 2 subtly different spellings for the same thing?
Having resorted to the job-dsl-plugin source code (here) it turns out the shorter names (listed first above) are basically pass-through methods to their longer-named counterparts, but with extra checks on the values passed to ensure they are in the expected list of actions.
So you can use either, but removeAction and removeViewAction will throw helpful errors if you pass an invalid string.
Related
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.
I'm in the midst of generating all our views using the Job DSL plugin.
The list views were created without a problem, but now I'm having troubles replacing my nested views.
If I copy & paste the example from https://jenkinsci.github.io/job-dsl-plugin/#path/nestedView , I get the following error:
ERROR: (ViewsGenerator.groovy, line 23) No signature of method: groovy.util.slurpersupport.NodeChild.call() is applicable for argument types: (foobar.jenkins.views.generator.ViewsGenerator$_run_closure1$_closure5) values: [foobar.jenkins.views.generator.ViewsGenerator$_run_closure1$_closure5#4e414e59]
Possible solutions: tail(), wait(), name(), max(), last(), any()
Line 23 is
views {
If I just use
nestedView('ZZZ_project-a') {
}
then Jenkins generates the nested view with that name, but of course it's empty!
I must be doing something very basic in a wrong way :-) but I can't figure it out! Any ideas?
I now tried using the given example directly in a Job DSL generator job (Use the provided DSL script), and that works!
What is the difference between my Groovy script and the one in the textbox?
Ok, after a lot of banging my head on the table :-) I finally found the solution.
As usual, the problem is with my software :-)
I have a helper class called Views which reads some XML etc. etc.
And there's a method called getViews() in there.
For convenience, I usually import such helper classes with
import static Views.*
So, within the Job DSL's nestedView there are views, and apparently Groovy got confused about what views to use, the ones from the Job DSL or my getViews().
I renamed that method to getAllViews(), and the problem was solved.
But getting there (I'm by no means a Groovy expert) was a pretty hard experience, since the error message was very cryptic to me.
We have a mix of DSL-seeded and manually created jobs on our Jenkins server.
I'd like to find all jobs NOT generated by DSL (or all generated by DSL at any time in the past).
I found no indication in job's config.xml that it was generated by DSL.
So, is it possible and how?
Well, I have the same problem as you.
I wonder how the link "Seed job" within the generated job is created. I don't see it in all of the generated jobs, either.
Unfortunately, I didn't get very far with my research.
In the script console, I listed the methods for one of my jobs (let's call it foo) :
Jenkins.instance.getItems().each {
if (it.getName() == 'foo') {
println it
it.class.getMethods().each { method ->
println method
}
}
};
However, I didn't see any methods containing jobdsl there.
I found a file $JENKINS_HOME/javaposse.jobdsl.plugin.ExecuteDslScripts.xml that contains generated job names and their seed jobs. But I don't know whether there is an official JobDSL API for reading it.
So... if you find more information, I'd be glad to know - good luck!
I've got a piece of code that works perfectly in all of the groovy interpreters I know of, including Jenkins scripting console. Yet it has a weird behavior when it comes to pipeline scripts.
def kvs = ['key1': 'value1', 'key2': 'value2']
println kvs
println kvs.inject(''){ s,k,v -> s+= "{'$k': '$v' } "}
First of all, the map is printed differently:
Expected: [key1:value1, key2:value2]
Got: {key1=value1, key2=value2}
Then, more of a problem, the yielded result differs drastically:
Expected: {'key1': 'value1' } {'key2': 'value2' }
Got: null
Both of these results were obtained with the following groovy version: 2.4.12.
(Though, outside of the pipeline script, I also tried versions 2.4.6 and 2.4.15 and always got the expected results)
Please note that I am not interested in workarounds. I only wish to understand why the behavior changed from normal groovy to pipeline script.
It is happening because the Jenkins pipeline code is not actually running this Groovy code directly it is interpreting it with a parser to apply script security to keep the Jenkins system secure amongst other things. To quote "Pipeline code is written as Groovy but the execution model is radically transformed at compile-time to Continuation Passing Style (CPS)." - see best practices https://jenkins.io/blog/2017/02/01/pipeline-scalability-best-practice/. In short, don't write complex Groovy code in your pipelines - try to use standard steps supplied by the pipeline DSL or plugins. Simple Groovy code in script sections can be useful in some scenarios however. Nowadays I am putting some of my more complex stuff in plugins that supply custom steps.
Often when looking at scripted jenkins pipeline code, I see this pattern...
step([$class: 'GitHubSetCommitStatusBuilder',
statusMessage: [content: 'Pipeline Started']])
I have not had any luck finding documentation on this technique and would love it if someone could explain what this is doing and when/why it is useful. I believe this is a way to instantiate and populate the members of an underlying groovy class - but more detail would be appreciated.
Also is this documented anywhere?
Here is a reference that briefly explains the syntax. Basically, you are providing the step() function a map of arguments in the form of name-value pairs. The first argument which is especially denoted by the name $class tells the function which class (plugin) to instantiate.
It also seems that this syntax is being deprecated in favor of shorter syntax, also explained in the same link.
I am also struggling with this syntax, but unfortunately have not found any doc yet.
I guess this syntax is used to doing the instance initialization.
All step classes implement interface BuildStep. After script loaded, all step instances initiated, then their perform method are invoked during build procedure.
All above is my conjecture.
There's also another quick reference from "Pipeline: Basic Steps" github repo documentation :
https://github.com/jenkinsci/workflow-basic-steps-plugin/blob/master/CORE-STEPS.md
Syntax
As an example, you can write a Pipeline script:
node {
sh 'make something'
step([$class: 'ArtifactArchiver', artifacts: 'something'])
}
Here we are running the standard Archive the artifacts post-build action (hudson.tasks.ArtifactArchiver), and configuring the Files to archive property (artifacts) to archive our file something produced in an earlier step. The easiest way to see what class and field names to use is to use the Snippet Generator feature in the Pipeline configuration page.
See the compatibility list for the list of currently supported steps.
Simplified syntax
Build steps and post-build actions in Jenkins core as of 2.2, and in some plugins according to their individual changelogs, have defined symbols which allow for a more concise syntax. Snippet Generator will offer this when available. For example, the above script may also be written:
node {
sh 'make something'
archiveArtifacts 'something'
}
NB: The Simplified syntax, makes reference to Plugin Steps parameters