How can I test my jenkins ci pipelines locally? - jenkins

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)

Related

Rebuild Jenkins Pipeline after specified Time if failed

I am using Pipelines to build our projects in Jenkins.
If the build of a pipeline fails I'd like to automatically start a new build after a predefined period of time.
Thus it is not possible for me to use the retry("3") command in the Jenkinsfiles because, the way I understand it, there would be no possibility for a delay.
Sleep or something similar wont do because it will block an executor.
The Naginator Plugin seems to do exactly what I need but it doesn't seem to work with pipelines.
I tried implementing it in the Jenkinsfile like:
post {
always {
echo '-------post called-------'
retryBuild {
rerunIfUnstable(true)
retryLimit(2)
fixedDelay(60)
}
echo '-------post finished-------'
}
}
This does not throw any errors and both echos will be shown in the pipeline build. However it doesn't do anything either.
Does anyone have any experience with a similar problem or is there potentially even a way to use Naginator (or other plugins) with Jenkins pipelines?

Is a Jenkinsfile valid standalone groovy?

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.

Use IDE to generate pipline script for jenkins

I need to overload jenkins functions to debug pipeline script in IDE.
I'm new to java/groovy etc. I'm going to write a several hundred lines scripted pipeline. Groovy is based on java. As I'm new I prefer the function name completion/suggestion and a debugging feature would be awesome where I can walk through the lines step by step and see what is in the vars.
I set up a eclipse Luna with the groovy-plugin. Which is actually working =)! (for newest eclipse the plugin is not yet ready). Also debugging is quiet cool!
But special jenkins expressions will still throw errors.
node(MasterName){ ... }
sh
...
Is there a chance to overload those functions?
Just killing the error, not performing any actions. Maybe converting it to a print like "I'm executing script XYZ" or "Switching to node BLUBB"?
The outcome should be a copy paste script, for checking in and running with jenkins without major changes.
Is there any better way?
In the end it turned out, that even if you omit the pipeline specific expressions, you will still have trouble. In some more complex situations e.g. calling a constructor with super in a extended class and executing a function afterwards, it does not behave the same then in my local python interpreter.
So what I did was an error to assume, my Ubuntu system default groovy interpreter would work the same like the jenkins interpreter. It would be nice to run a debugger inside the jenkins environment, or going step by step through the pipeline script and see how it is actually working without a print in every second line.

Jenkins pipeline groovy testing in shell

Can jenkins pipeline scripts be tested using groovysh or groovy scriptname to run tests for validation without using the Jenkins UI
For example for a simple script
pipeline {
stages {
stage ('test') {
steps {
sh '''
env
'''
}
}
}
}
running a test like this, depending on the subset of scripting gives:
No signature of method: * is applicable for argument types
groovysh_evaluate.pipeline()
or for
stage('test'){
sh '''
env
'''
}
reports:
No signature of method: groovysh_evaluate.stages()
or simply
sh '''
env
'''
reports:
No signature of method: groovysh_evaluate.sh()
The question may be which imports are required and how to install them outside of a jenkins installation?
Why would anyone want to do this?
Simplify and shorten iterating over test cases, validation of library versions without modifying jenkins installations and other unit and functional test scenarios.
JenkinsPipelineUnit is what you're looking for.
This testing framework lets you write unit tests on the configuration and conditional logic of the pipeline code, by providing a mock execution of the pipeline. You can mock built-in Jenkins commands, job configurations, see the stacktrace of the whole execution and even track regressions.

How to execute groovy/java code in the context of a jenkins-pipeline slave node block?

In this snippet:
stage('build') {
node ('myslave') {
git(url: 'git#hostname:project.git')
println(InetAddress.getLocalHost().getHostName())
}
}
The git step is executed correctly and checks out code into node's workspace.
But why do I get Masters' hostname when executing the second command?
For example, this is not working also in the context of a node() {}
new File("${WORKSPACE}).listFiles()
Which does not actually iterate the ${WORKSPACE} folder
All Groovy code in an Pipeline script is executed on the master. I'm been unable to find any way to execute a generic groovy code on the slave, not due to lack of functionality in the Jenkins core, but problems with Pipeline groovy and serialisation of objects. Found this related question which addresses remoting in groovy.
It is however possible to do file operations on the slave side, see this answer for example how you can access files on the slave.

Resources