In Jenkins, I want to automatically run a function on load of the shared library, which is loaded implicitally on a global level. This would allow me to enforce certain functions in every pipeline.
This means, a user would not have to define anything in the pipeline script itself to have it run.
What I tried:
//src/org/test/Always.groovy
#!/usr/bin/env groovy
package org.test
class Always implements Serializable {
Always() {
println "Always print me"
}
}
Always()
This does not appear to do anything, however. I would expect it to always instantiate the Always class and print "Always print me".
An global-pre-script-plugin exists that seems to fit your use case. It can execute a groovy script before each job / build starts. I am not sure if the script can load shared libraries and inject methods (maybe as Closure variable?) from it. This is something we would need to test :)
The plugin's last commit is from March 2020 though, so looks rather unmaintained to me.
This plugin makes it possible to execute a groovy script at the start
of every job
Features:
Applies to all jobs/builds run in the server
Executes a groovy script when a build starts Injects any number of variables in the build
Injects properties based on the content of another property
Executes a script when the build starts
Very light plugin
Failures in the script do not abort the build
Related
I have a groovy script that runs as a shared library and get jenkins build details.
projects = Jenkins.instance.getJob('ABB').getItems()
for( build in projects.getAllJobs())
{
//process build data
build.getDuration();
build.getTime();
etc.
}
Can some one tell me how I can see all the get methods (all metadata related to build) that I can access by using the build variable? Is there any Javadoc for this? I am not able to find? As of now it access Duration and Time but I want to know what all info can I get.
Yes, Jenkins provides Javadoc: https://javadoc.jenkins.io/
build is an instance of the hudson.model.Run interface.
Of course the instance may provide more details because every type of job (FreeStyle, Pipeline etc.) may return an object with more details. For example new pipelines use org.jenkinsci.plugins.workflow.job.WorkflowRun.
The easiest option is to check the class and next search for its Javadoc :)
for (def build in projects.allJobs) {
echo "${build.class}"
}
A script generates a properties file to work-space in an Execute shell block in the Build section. This file is available at work-space after script execution and in case of Failed build (Conditional steps (multiple) block in the Build section) this properties file will be injected. My Jenkins job sends an E-mail (Editable Email Notification block) in case if Failed build and it should contains the variable from properties file but it doesn't see this variable. FYI: This block can use other environment variables.
I have cross-checked the properties file and it contains the required variable in every case.
Properties file in work-space:
Environment variable injection from properties file:
This Steps to to run if condition is met block contains more other actions and these work fine. It means the running can reach this block.
Editable Email Notification block in Post-build:
If I check the Environment Variables option in a build, I can see the variable:
But when I get the mail, it doesn't contain the variable:
Any idea how can I solve it or what should I change?
NOTE: The variable is unique and not really related to Gerrit so I cannot use another variable which comes form Gerrit. Just the name of var is a little tricky.
I have found the answer for my question. The Jenkins or the plugin has limitation. It cannot handle the Failure state. If the previous execute shell block is failed then the running won't reach the Conditional steps (multiple) block.
On the other hand, I have found a "workaround" for this problem.
1. step
You need to exit from the Execute shell block with a specific return code. Eg.: 111
2. step
You need to set the Exit code to set build unstable filed to your specific exit code. (You can find this field in advanced option of Execute shell block.) As you can see in the below picture.
3. step
Set the Conditional steps (multiple) block to handle the Unstable state. With this solution the running is able to run into Conditional steps (multiple) block.
4. step
Create an Execute shell block inside the Conditional steps (multiple) block after you prepare everything what you want in case of job failed. It means after this block your job status changes to Failed from Unstable.
Whit this solution you can handle the failed job and in the end you will get a real failed job (not unstable).
Not the most elegant solution but it works.
So I have just created a geb script that tests the creation of a report. Let's call this Script A
I have other test cases I need to run that are dependent on the previous report being created, but I still want the Script A to be a stand alone test. we will call the subsiquent script Script B
Furthermore Script A generates a pair of numbers that will be needed in subsequent scripts (to verify data got recorded accurately)
Is there a way I can setup geb such that Script B executes 'Script Aand is able to pull those 2 numbers fromScript Ato be used inScript B`?
In summary there will be a number a scripts that are dependent on the actions of Script A (which is itself a test) I want to be able to modularize Script A so that it can be executed from other scripts. What would be the best way to do this?
For reuse and not repeating yourself I would put the report creation into a separate method call in a new class such as ReportGenerator, this would generate the report given a set of parameters (if required) and return the report figures for use in whatever test you like.
You could then call that in any spec you want, with no reliance on other specs.
I'm attempting to write a global function script that uses groovy.sql.SQL.
When adding the annotation #GrabConfig(systemClassLoader=true) I get an exception when using the global function in Jenkinsfile.
Here is the exception:
hudson.remoting.ProxyException: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
General error during conversion: No suitable ClassLoader found for grab
Here is my code:
#GrabResolver(name='nexus', root='http://internal.repo.com')
#GrabConfig(systemClassLoader=true)
#Grab('com.microsoft.sqlserver:sqljdbc4:4.0')
import groovy.sql.Sql
import com.microsoft.sqlserver.jdbc.SQLServerDriver
def call(name) {
echo "Hello world, ${name}"
Sql.newInstance("jdbc:sqlserver://ipaddress/dbname", "username","password", "com.microsoft.sqlserver.jdbc.SQLServerDriver")
// sql.execute "select count(*) from TableName"
}
Ensure that the "Use groovy sandbox" checkbox is unticked (it's below the pipeline script text box).
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, not every Groovy feature is supported.
I'm not sure about #Grab support. It is discussed in JENKINS-26192 (which is declared as resolved, so maybe it works now).
Extract from a very interesting comment:
If you need to perform some complex or expensive tasks with
unrestricted Groovy physically running on a slave, it may be simplest
and most effective to simply write that code in a *.groovy file in
your workspace (for example, in an SCM checkout) and then use tool and
sh/bat to run Groovy as an external process; or even put this stuff
into a Gradle script, Groovy Maven plugin execution, etc. The workflow
script itself should be limited to simple and extremely lightweight
logical operations focused on orchestrating the overall flow of
control and interacting with other Jenkins features—slave allocation,
user input, and the like.
In short, if you can move that custom part that needs SQL to an external script and execute that in a separate process (called from your Pipeline script), that should work. But doing this in the Pipeline script itself is more complicated.
A custom plugin we wrote for an older version of Jenkins uses an EnvironmentContributingAction to provide environment variables to the execution so they could be used in future build steps and passed as parameters to downstream jobs.
While attempting to convert our build to workflow, I'm having trouble accessing these variables:
node {
// this step queries an API and puts the results in
// environment variables called FE1|BE1_INTERNAL_ADDRESS
step([$class: 'SomeClass', parameter: foo])
// this ends up echoing 'null and null'
echo "${env.FE1_INTERNAL_ADDRESS} and ${env.BE1_INTERNAL_ADDRESS}"
}
Is there a way to access the environment variable that was injected? Do I have to convert this functionality to a build wrapper instead?
EnvironmentContributingAction is currently limited to AbstractBuilds, which WorkflowRuns are not, so pending JENKINS-29537 which I just filed, your plugin would need to be modified somehow. Options include:
Have the builder add a plain Action instead, then register an EnvironmentContributor whose buildEnvironmentFor(Run, …) checks for its presence using Run.getAction(Class).
Switch to a SimpleBuildWrapper which defines the environment variables within a scope, then invoke it from Workflow using the wrap step.
Depend on workflow-step-api and define a custom Workflow Step with comparable functionality but directly returning a List<String> or whatever makes sense in your context. (code sample)
Since PR-2975 is merged, you are able to use new interface:
void buildEnvVars(#Nonnull Run<?, ?> run, #Nonnull EnvVars env, #CheckForNull Node node)
It will be used by old type of builds as well.