I need to grab the "Build Triggers -> Build Periodically" values using a groovy script. I need to check if it is enabled and what the Schedule values are but I have no luck while searching through Jenkins' github and the javadoc.jenkins api documentation.
List keys = new ArrayList(job.getTriggers().keySet());
for (int i = 0; i < keys.size(); i++) {
Object obj = keys.get(i);
if(obj.getDisplayName().contains("Build periodically")) {
println job.fullName + "," + job.getTriggers().get(keys.get(i)).spec
}
}
Related
some days ago I bumped into a code snippet used to override the default configuration of the Jenkins plugin "GitHub SCM Source" (unknown author):
Closure configOverride(String repo, int id, String cred) {
return {
it / sources / 'data' / 'jenkins.branch.BranchSource' << {
source(class: 'org.jenkinsci.plugins.github_branch_source.GitHubSCMSource') {
id(id)
scanCredentialsId(cred)
checkoutCredentialsId('SAME')
repoOwner('owner')
repository(repo)
includes('*')
buildOriginBranch('true')
buildOriginBranchWithPR('true')
buildOriginPRMerge('false')
buildOriginPRHead('false')
buildForkPRMerge('true')
buildForkPRHead('false')
}
}
}
}
All it's good except that I can't understand the following line:
it / sources / 'data' / 'jenkins.branch.BranchSource' << { ... }
I tried to find some explanation about the use of '/' in groovy but no luck. Maybe I don't know what exactly to search.
Could someone help me please with a link to the docs or a short explanation.
This is overloading of
operators
Groovy allows you to overload the various operators so that they can be used with your own classes. Consider this simple class:
class Bucket {
int size
Bucket(int size) { this.size = size }
Bucket plus(Bucket other) {
return new Bucket(this.size + other.size)
}
}
Just by implementing the plus() method, the Bucket class can now be used with the + operator like so:
def b1 = new Bucket(4)
def b2 = new Bucket(11)
assert (b1 + b2).size == 15
For / one would override T div(T x)
This code snippet is used in Jenkins DSL for the "multibranchPipelineJob". The closure configOverride is used to generate an XML object which replace the default configuration in config.xml on the following path "sources/data/jenkins.branch.BranchSource".
In my one jenkins pipeline job, I use createSummary of post build plugin to add some log url on the jenkins job UI. For the files moved to somewhere else, so I want to change the url. Is there a way to reset the information for this build?
manager.createSummary("red/yellow/green.gif")
.appendText("""log""", false, false, false, "black")
Any tips/advice are appriciated, thanks a lot!
I finally solved it using BadgeSummaryAction.
Jenkins.instance.getItemByFullName(jobName).builds.findAll { it.number > startnumber &&
it.number < endnumber}.each {
List<Action> actions = it.getActions();
List<BadgeSummaryAction> summaryActions = it.getActions(BadgeSummaryAction.class);
String iconText = "green.gif"
for(int i =0; i<summaryActions.size();i++) {
BadgeSummaryAction currentAction = summaryActions.get(i);
String sActionText = currentAction.getText()
if(sActionText.contains("FAILED")){
iconText = "red.gif"
}else if(sActionText.contains("UNSTABLE")){
iconText = "yellow.gif"
}
actions.remove(currentAction);
BadgeSummaryAction summary = new BadgeSummaryAction(iconText)
summary.appendText(replaceText, false);
it.addAction(summary);
}//end of for
}
I am working on Jenkins version 2.32.1 pipeline. I want to extract the parameters that were chosen in the previous build of my job.
In our previous Jenkins instance ( 1.627 ) we were using jenkins.model.Jenkins.instance.getItem(job).lastBuild.getBuildVariables().get(param);
For some reason this is not working in this version (I also tried disabling the sandbox).
Any pointers on how to accomplish it?
Simplified version of the previous script:
def build = Jenkins.get().getItems(org.jenkinsci.plugins.workflow.job.WorkflowJob).find {it.displayName == 'YOUR_JOB_NAME_HERE'}?.getLastBuild()
build.actions.find{ it instanceof ParametersAction }?.parameters.each {echo "${it.name}=${it.value}"}
Actually a little bit shorter version for those who want to get the params for the current build from the previous run and is working on new 2+ Jenkins versions.
To get 1 particular parameter:
def cls = currentBuild.getPreviousBuild().getRawBuild().actions.find{ it instanceof ParametersAction }?.parameters.find{it.name == 'cls'}?.value
Get all params respectfully:
def cls = currentBuild.getPreviousBuild().getRawBuild().actions.find{ it instanceof ParametersAction }?.parameters
Something like this might work, based on https://stackoverflow.com/a/19564602/3920342:
def h = hudson.model.Hudson.instance
def r = null
h.getItems(org.jenkinsci.plugins.workflow.job.WorkflowJob).each {project ->
if (project.displayName.equals('YOUR_JOB_NAME')) {
r = project
}
}
r.getBuilds().findAll { b -> // here we loop over all past builds, apply some filter if necessary
def p = b?.actions.find{ it instanceof ParametersAction }?.parameters
p.each {
echo "parameter ${it.name}: ${it.value}"
}
}
For those who are not able to access getActions() due to admin permissions i.e. facing the following error:
Scripts not permitted to use method hudson.model.Actionable getActions
They can copy the parameter variables to the env and get them using build.previousBuild.buildVariables
stage('Prepare environment') {
steps {
script {
env.MY_PARAM_COPY = "${MY_PARAM}"
}
}
}
println("MY_PARAM in previous build: ${currentBuild.previousBuild.buildVariables["MY_PARAM_COPY"]}")
That's how I made it works, answer from #dan.goriaynov and #jherb caused some CPS closure issues for me.
(the gist of the code is to allow only greater TAG number than the previous one to be deployed)
stage('Validate build number') {
def previous_build = currentBuild.getPreviousBuild().getRawBuild();
def PREVIOUS_TAG = '';
for (int i = 0; i < previous_build.allActions.size(); i++) {
if (previous_build.allActions[i] in hudson.model.ParametersAction) {
PREVIOUS_TAG = previous_build.allActions[i].getParameter("TAG").value
}
}
if (PREVIOUS_TAG.toInteger() > TAG.toInteger()) {
echo PREVIOUS_TAG
error('TAG number needs to be greater than the previous one')
}
}
I'm trying to run a few suits with tests in parallel as a part of workflow. So I create a map, put there a couple of closures and pass it to parallel step. The issue that I'm facing related to name of the HTML report. After execution, I see a few identical "HTML Report" links, so I can't open specific report - all of them have the same name. I had tried to make this name unique, but these attempts were not successful. Does anyone faced similar thing?
def testExecutions = [:]
def testExecution = {
node {
//code to run tests
publishHTML(target: [allowMissing: false,
alwaysLinkToLastBuild: false,
keepAll: true, reportDir: 'target/reports',
reportFiles: 'index.html',
reportName: "HTML Report " + it)
}
}
for (int i = 0; i < 2; i++) {
final k = i
testExecutions.put("tests $k", {testExecution(k)})
}
parallel(testExecutions)
Maybe the testExecution() function lacks the it parameter?
def testExecution(it) = {
node {
....
}
}
It seems that your node is on the wrong level. Now this rises a really interesting question.
My guess would be that when your workers would actually get the node to execute k or it would have be already evaluated by the master, meaning that from the point of view of parallel call the closure implicit argument would always be equal to 1. (although I consider myself not educated enough with Jenkins workflow and groovy to say for sure)
This version should work for you
def testExecutions = [:]
def testExecution = {
println "HTML Report " + it
}
for (int i = 0; i < 2; i++) {
final k = i
testExecutions.put("tests $k", {node{testExecution(k)}})
}
parallel(testExecutions)
I'm trying to figure out how to exclude a list of folders from the code coverage report generated by jacoco, which is launched by Jenkins.
It seems possible to exclude classes, but not folders, which is annoying for me as I've started using a pretty big library for an online payment system. Running those unit tests means constantly creating test accounts on that platform and having to delete them again. Every single tine Jenkins runs.
And it would be far simpler to just have the folders excluded than having to exclude every single one of the classes.
To exclude entire directories by changing the Jenkins JaCoCo plugin configuration you would need to add an entry to the 'Exclusions' field.
For instance, if you want to exclude any files under any directory named 'test' you would add the following exclusion:
**/test/**
Keep in mind that if you want to add multiple exclusions you have to separate each one by a comma and there can be no spaces (due to a bug with the plugin).
Here is my JaCoCo plugin configuration:
Example JaCoCo Plugin Configuration
If you are using pipelines and Jenkinsfile you can use the following as an example of the settings (assumes gradle):
stage("Check code quality and coverage") {
steps{
sh "./gradlew jacocoTestReport sonarqube -x check"
step( [$class: 'JacocoPublisher',
exclusionPattern: '**/*Exception*,**/*Configuration*,**/ApiApplication*,**/*Test*'] )
}
}
Of note here is the exclusionPattern is comma separated and NO SPACES between the multiple exclusion patterns.
The easiest way to see the full list of potential settings is to look at the code:
https://github.com/jenkinsci/jacoco-plugin/blob/master/src/main/java/hudson/plugins/jacoco/JacocoPublisher.java
And check out the #DataBoundSetter's
public JacocoPublisher() {
this.execPattern = "**/**.exec";
this.classPattern = "**/classes";
this.sourcePattern = "**/src/main/java";
this.inclusionPattern = "";
this.exclusionPattern = "";
this.skipCopyOfSrcFiles = false;
this.minimumInstructionCoverage = "0";
this.minimumBranchCoverage = "0";
this.minimumComplexityCoverage = "0";
this.minimumLineCoverage = "0";
this.minimumMethodCoverage = "0";
this.minimumClassCoverage = "0";
this.maximumInstructionCoverage = "0";
this.maximumBranchCoverage = "0";
this.maximumComplexityCoverage = "0";
this.maximumLineCoverage = "0";
this.maximumMethodCoverage = "0";
this.maximumClassCoverage = "0";
this.changeBuildStatus = false;
this.deltaInstructionCoverage = "0";
this.deltaBranchCoverage = "0";
this.deltaComplexityCoverage = "0";
this.deltaLineCoverage = "0";
this.deltaMethodCoverage = "0";
this.deltaClassCoverage = "0";
this.buildOverBuild = false;
}
Exclude classes from sonar analysis by specifying sonar.jacoco.excludes parameter like this:
sonar.jacoco.excludes=*/exceptions/*:*/dto/*