I want to add timestamps() and colorizeOutput() features to our pipeline libraries. I find the wrappers {} in Jenkins documentation:
job('example') {
wrappers {
colorizeOutput()
timestamps()
}
}
I don`t get how to add wrappers to out library which looks like that:
// file ..src/helpers/Builder.groovy
package helpers.sw_main
def doSomething() {
// some Groovy stuff here
}
def doSomethingElse() {
// do something else
}
Our job pipeline looks like that:
#!/usr/bin/env groovy
// this is our library with custom methods
#Library('ext-lib')
def builder = new helpers.Builder()
node {
try {
stage('Some Stage') {
builder.doSomething()
}
}
catch (err) {
throw err
}
}
So, I want to add timestamps and ansi-colors to every function from library. Of course, I can do it with wrapping every function with
timestamps() {
colorizeOutput() {
// function body
}
}
But its a little stupid.
So can I easily wrap pipeline or library?
One solution to your problem is to use Global Variables (/vars/xxxxx.groovy).
To create an own build step, add a Global Variable like /vars/myOwnStep.groovy:
def call(STAGE_NAME, Closure closure) {
// do something
// return something if you like to
}
whcih you can call like this
myOwnStep("Step-name") {
// what ever you want to do
}
in your pipeline script.
Another possibility is to "overwrite" the sh step. Therefore create a file called /vars/sh.groovy with this code:
def call(String script, String encoding=null, String label=null, boolean returnStatus=null, boolean returnStdout=null) {
timestamps {
return steps.sh(script: script, endoding: encoding, label: label, returnStatus: returnStatus, returnStdout: returnStdout)
}
}
def call(Map params = [:]) {
return call(params.script, params.get('encoding', null), params.get('label', null), params.get('returnStatus', false), params.get('returnStdout', false))
}
(This can be done for other steps too, but he parameters have to match.)
I just added a GitHub repository with some examples: https://github.com/datze/jenkins_shared_library (untested!)
Related
I just asked about how to mock jenkins step/global vars for testing a custom step and got help here
This is how I'm doing that now:
// vars/myCustomStep.groovy
def call(Map config) {
def paramOne = config.paramOne
container('my-container') {
echo paramOne
sh 'printenv'
}
}
// test/vars/myCustomStep.groovy
class myCustomStepTest {
Binding binding
def shell
def myCustomStep
#Before
public void setUp() throws Exception {
// Instantiate shell object and attach methods for mocking jenkins steps
binding = new Binding()
binding.echo = { String message -> println "$message" }
binding.sh = { String command -> println "sh step: $message" }
// How do I mock this??? this returns "No signature of method: myCustomStep.container() is applicable for argument types..."
binding.container = { Closure closure -> closure }
shell = new GroovyShell(binding)
// Instantiate groovy script
myCustomStep = shell.parse( new File( 'vars/myCustomStep.groovy' ) )
}
#Test
public void "sdfsdfsdf"() throws Exception {
myCustomStep paramOne: "sdlfsdfdsf"
}
}
My current challenge is figuring out how to mock things like script{} and container{} closures. I can't modify the structure of myCustomStep.groovy because this is jenkins specific. The behavior I want is for the test to essentially just ignore the container('xxx'){} method and only execute what is inside it.
I would like to know if there is a way to access the Jenkins Workflow script object during its execution.
I have a shared library, and I can pass this object to any groovy class as an argument, either directly from the Jenkins file, using 'this' keyword, or from any DSL in the vars folder, also using the 'this' keyword.
But I would like to access it using a method, even if this imply using reflexivity.
Is that possible?
Here example with pipeline, where this is a script object. Some other examples here:
MyClass myClass = new MyClass()
pipeline {
agent any
environment {
VAR1 = "var1"
VAR2 = sh(returnStdout: true, script: "echo var2").trim()
VAR3 = "var3"
}
stages {
stage("Stage 1") {
steps {
script {
myClass.myPrint(this, "${VAR1}", "${VAR2}", "${VAR3}")
}
}
}
}
}
class MyClass implements Serializable {
void myPrint(def script, String var1, String var2, String... vars) {
script.echo "myPrint: ${var1}"
}
}
I have a simple Declarative Pipeline with function inside. How to correctly use named arguments for a function?
def getInputParams(param1='a', param2='b') {
echo "param1 is ${param1}, param2 is ${param2}"
}
pipeline {
...
...
stages {
stage('Test') {
steps {
getInputParams(param1='x', param2='y')
}
}
}
}
I cannot understand why named params become null in function?
[Pipeline] echo
param1 is null, param2 is null
...
Well, I'm able to call function like getInputParams('x', 'y'), but it's not human readable (arguments amount may increase in future)
Groovy is executed inside the Jenkinsfile so you have to follow its syntax for named arguments.
foo(name: 'Michael', age: 24)
def foo(Map args) { "${args.name}: ${args.age}" }
Quote from Groovy's named arguments:
Like constructors, normal methods can also be called with named
arguments. They need to receive the parameters as a map. In the method
body, the values can be accessed as in normal maps (map.key).
def getInputParams(Map map) {
echo "param1 is ${map.param1}, param2 is ${map.param2}"
}
pipeline {
...
stages {
stage('Test') {
steps {
getInputParams(param1: 'x', param2: 'y')
}
}
}
}
If you are using groovy, use this.
def getInputParams(def param1, def param2) {
println("param1 is "+ param1 + ", param2 is " + param2)
}
pipeline {
...
...
stages {
stage('Test) {
steps {
getInputParams(x, y)
}
}
}
}
Hi!
I need to pass data from one step to another in a Jenkins pipeline. Something like this:
node {
// myPipelineStep is "my" own hello world pipeline step based on hello-world archetype, and I want it to return a variable that I have inside the plugin
def return_value = myPipelineStep inputVariable: value
// Then I want to do something else, a new step, where I use this value
sh 'echo $return_value'
//But the problem is I dont know how to return something from my pipeline step
}
But in the archetype empty-plugin the perform()-function where the action should take place is void.. So it is not possible to return something here.
And the same goes for the hello-world acrhetype.
Anyone with any leads?
Can you modify what is in the method ?? if so, create a global variable outside and assign the value inside the method.
Now the variable will have the value and you can use it in the other method
E.g.
node{
def isVaild
void perform(.....) {
//do stuff
isValid =true;
}
#Override
void perform(.....) {
//do stuff
if(isValid){
}
}
}
It should work :)
My jenkins file looks like below:
import groovy.json.*
def manifestFile = "C:\\manifest.yml"
node {
stage('Build') {
}
stage('Deploy') {
checkDeployStatus()
}
}
def boolean checkDeployStatus() {
echo "${manifestFile}"
return true
}
The exception that i am getting is below:
groovy.lang.MissingPropertyException: No such property: manifestFile for class: groovy.lang.Binding
at groovy.lang.Binding.getVariable(Binding.java:63)
How do i access variables outside the node?
Groovy has a different kind of scoping at the script level. I can't ever keep it all sorted in my head. Without trying explain all the reasons for it (and probably not doing it justice), I can tell you that (as you have seen), the manifestFile variable is not in scope in that function. Just don't declare the manifestFile (i.e. don't put def in front of it). That will make it a "global" (not really, but for your purposes here) variable, then it should be accessible in the method call.
try this
import groovy.json.*
manifestFile = "C:\\manifest.yml"
node {
stage('Build') {
}
stage('Deploy') {
checkDeployStatus()
}
}
def boolean checkDeployStatus() {
echo "${manifestFile}"
return true
}