I am unable to execute following script in jenkins script consol.
job('testjob') {
using('template_job')
configure { node ->
node / scm / branches / 'hudson.plugins.git.BranchSpec' / name('main')
}
}
i am getting below error
groovy.lang.MissingMethodException: No signature of method: Script1.job() is applicable for argument types: (java.lang.String, Script1$_run_closure1) values: [testjob, Script1$_run_closure1#4eaafbe6]
Possible solutions: run(), run(), any(), wait(), dump(), grep()
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:81)
The script you are trying to run is a Job DSL script.
It is not intended to run in the Jenkins script console menu and therefore you get that exception, the DSL script should be executed in a dedicated Process Job DSLs build step (usually in a freestyle job). Use the following Official Documentation Guide to get started with the Jon DSL plugin and instructions on how to use it.
In addition here is an excellent Tutorial for using the Job DSL Plugin.
BTW, you can use the Job DSL Playground to create and test your configure blocks, but the playground only supports the DSL API that is available in the online API Reference - as oppose to the complete DSL API reference that is available in your Jenkins installation at https://your.jenkins.installation/plugin/job-dsl/api-viewer/index.html.
Related
I'm trying to wrap my head around how this declarative Jenkinsfile is Groovy. I want to write supporting code to execute this outside the Jenkins environment, in pure Groovy, if that's possible. I've been writing example groovy code but still am unsure what "pipeline", "agent", and "stages" are.
Any tips to understand this structure is appreciated
EDIT: I edited this question with simplified code below. I'm just wondering if there is a way that this can be turned into valid groovy code without the preprocessor/groovyshell environment that is utilized by Jenkins
pipeline {
stages {
// extra code here
}
}
No, you can't run Jenkinsfile as a standalone Groovy script. In short, Jenkins executes the pipeline code inside a pre-configured GroovyShell that knows how to evaluate things like pipeline, agent, stages, and so forth. However, there is a way to execute Jenkinsfie without the Jenkins server - you can use JenkinsPipelineUnit test library to write JUnit/Spock unit tests that will evaluate your Jenkinsfile and display the call stack tree. It uses mocks, so you can treat it as interaction-based testing, to see if a specific part of your pipeline gets executed. Plus, you can catch some code errors prior to running the pipeline on the server.
A simple unit test for the declarative pipeline can look like this:
import com.lesfurets.jenkins.unit.declarative.*
class TestExampleDeclarativeJob extends DeclarativePipelineTest {
#Test
void should_execute_without_errors() throws Exception {
def script = runScript("Jenkinsfile")
assertJobStatusSuccess()
printCallStack()
}
}
You can find more examples in the official README.md - https://github.com/jenkinsci/JenkinsPipelineUnit
Alternatively, you can try Jenkinsfile Runner command-line tool that can execute your Jenkinsfile outside of the Jenkins server - https://github.com/jenkinsci/jenkinsfile-runner
UPDATE
I edited this question with simplified code below. I'm just wondering if there is a way that this can be turned into valid groovy code without the preprocessor/groovyshell environment that is utilized by Jenkins.
Your pipeline code example looks like a valid Jenkinsfile, but you can't turned it into a Groovy code that can be run e.g. from the command-line as a regular Groovy script:
$ groovy Jenkinsfile
This won't work, because Groovy is not aware of the Jenkins Pipeline syntax. The syntax is added as a DSL via the Jenkins plugin, and it uses a dedicated GroovyShell that is pre-configured to interpret the pipeline syntax correctly.
If you are interested in checking if the syntax of the Jenkins Pipeline is correct, there are a few different options:
npm-groovy-lint (https://github.com/nvuillam/npm-groovy-lint) can validate (and even auto-fix) the syntax of your Jenkinsfile without connecting to the Jenkins server,
Command-Line Pipeline Linter (https://www.jenkins.io/doc/book/pipeline/development/#linter) can send your pipeline code to the Jenkins server and validate its syntax.
These are a few tools that can help you with catching up the syntax errors before you run the pipeline. But that's just a nice addon to your toolbox. The first step, as always, is to understand what the syntax means, and the official documentation (https://www.jenkins.io/doc/book/pipeline/syntax) is the best place to start.
My jenkins job "Build" configuration has
3 Execute shell - build tasks
2 Post build action
Is there any way to get the runtime of each buildtask and postbuild action ?
Not directly, which is why:
I use a Jenkins plugin timestamper to add the timestamps in the logs, giving me the opportunity to extract each task duration.
there are plugins like additional-metrics-plugin or build-metrics which collect job duration (but not necessarily task or post-build task duration): they could be good starting point for making a custom plugin which would collect what you need.
I have defined a shared library in Jenkins:
import com.codependent.jenkins.pipelines.Utils
def call(List<String> mavenGoals){
def processedMavenGoals = mavenGoals.join ' '
pipeline {
agent any
...
}
If i call this from my project's Jenkinsfile like this it works ok:
#!groovy
#Library('jenkins-pipeline-shared-library-example') _
buildPipeline(['clean', 'install'])
However if I omit the parethesis as Groovy syntax allows:
#!groovy
#Library('jenkins-pipeline-shared-library-example') _
buildPipeline ['clean', 'install']
The execution shows the folloing exception. Why?
org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: unclassified getAt method buildPipeline[java.util.ArrayList]
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetArray(SandboxInterceptor.java:451)
at org.kohsuke.groovy.sandbox.impl.Checker$10.call(Checker.java:413)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetArray(Checker.java:418)
at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getArray(SandboxInvoker.java:45)
at com.cloudbees.groovy.cps.impl.ArrayAccessBlock.rawGet(ArrayAccessBlock.java:21)
at WorkflowScript.run(WorkflowScript:3)
at ___cps.transform___(Native Method)
I have had a similar issue after updated jenkins.
In my case the stacktrace also showed a org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException[...]
Reason
Jenkins has a security plugin that blocks certain method calls in Jenkinsfile s.
Solution
To allow these calls that sometimes are harmless:
Go to: http://JENKINS_HOST/scriptApproval/ ( Official Documentation )
Approve the action that has been denied in the Jenkinsfile
Rerun the failed build to see Jenkinsfile work
In most cases <JENKINS_SERVER_URL>/scriptApproval should be enough. However there are cases when the forbidden method does not appear in /scriptApproval due to some reasons. Some of them are explained here: Why-am-I-unable-to-see-a-method-in-In-process-Script-Approval.
In such case you can try either programmatically force the method approval (see the answer here:
https://stackoverflow.com/a/48234868/4807875) or manually update the $JENKINS_ROOT/scriptApproval.xml file on the Jenkins server. The latter will require root permissions and Jenkins server restart to take effect (the option "Reload Configuration from Disk" will not work).
P. S.: I did not test how it works with the BlackList methods.
I am writing a number of ci scripts for jenkins pipelines. A frequently occuring pattern is
dir("path/to/stuff"){
do_stuff()
}
I would like to 'test-run' these scripts to achieve a (very) short feedback loop. But I immediately run into the fact that this dir method is not an 'official' groovy method.
$ groovy ci/test-ci-scripts.groovy
Caught: groovy.lang.MissingMethodException: No signature of method:
test-ci-scripts.dir() is applicable for argument types: ....
What do I need to import to get this running?
just use single apostrophe's
dir('path') {
// some block
}
works fine for me. (You can find dir in Jenkins Pipeline Snippet Generator)
What are seed jobs in Jenkins and how does it work ?
Can we create a new job from seed job without using github ?
That depends on context. Jenkins itself does not provide "seed jobs".
There's plugins that allow creating jobs from other jobs, like the excellent Job-DSL plugin. With that, you can create jobs where a groovy script creates a larger number of jobs for you.
The Job-DSL plugin refers to those jobs as "seed jobs" (but they're regular freestyle or pipeline jobs). The Job-DSL plugin does not require a github connection.
The seed job is a normal Jenkins job that runs the Job DSL script; in turn, the script contains instructions that create additional jobs. In short, the seed job is a job that creates more jobs. In this step, you will construct a Job DSL script and incorporate it into a seed job. The Job DSL script that you’ll define will create a single freestyle job that prints a 'Hello World!' message in the job’s console output.
A Job DSL script consists of API methods provided by the Job DSL plugin; you can use these API methods to configure different aspects of a job, such as its type (freestyle versus pipeline jobs), build triggers, build parameters, post-build actions, and so on. You can find all supported methods on the API reference site.
The jobs we used for creating new jobs are called Seed Jobs and this seed job generates new jobs using Jenkins files (using JobDSL plugin).
Here, we disabling this feature (Enable script security for Job DSL scripts)
Jenkins Dashboard→ Manage Jenkins → Configure Global Security
Way to create seed job :
JobDSL scripts for generating new jobs.
Job1.groovy
job("Job1"){
description("First job")
authenticationToken('secret')
label('dynamic')
scm {
github('Asad/jenkins_jobDSL1', 'master')
}
triggers {
gitHubPushTrigger()
}
steps {
shell ('''
echo "test"
''')
}
}
buildPipelineView('project-A') {
title('Project A CI Pipeline')
displayedBuilds(5)
selectedJob('Job1')
showPipelineParameters()
refreshFrequency(60)
}
and create same way others Job2.groovy and so on.
For Jenkins Job DSL documentation:-
Follow https://jenkinsci.github.io/job-dsl-plugin/
Think about a job - what is it actually ?
It is actually just a java/jre object that represents like this
How you generates such job/build ?
Configure Jenkins UI -> rest api to Jenkins url -> Jenkins service receive your call on the relevant endpoint -> calling to the relevant code/method and generate this new job
How Seed job will make it ?
Configure seed job on Jenkins UI only once -> run this seed job - > this code run against the internal Jenkins methods and skip all the manual process describes above
Now, when your code can talk directly to Jenkins code , things are much easier.just update your code on the relevant repo - and you are done