Jenkins - check if specific job is running with hudson classes - jenkins

I need to check if specific job is running from another job. I dont want use API or plugins. Just bare hudson model.
I already tried some properties of Jenkins.instance.getItemByFullName('folder/job').lastBuild but they either returning whole job status (stable/unstable) or there is no RUNNING results. I even seen that there is a script which finds current running executors. So i dont believe that there is no way of checking running jobs.
https://wiki.jenkins.io/display/JENKINS/Find+builds+currently+running+that+has+been+executing+for+more+than+N+seconds
import com.cloudbees.groovy.cps.NonCPS
import jenkins.model.*
import hudson.model.Result
#NonCPS
def getProject(projectName) {
def project = jenkins.model.Jenkins.instance.getItemByFullName(projectName)
if (!project) {error("Project not found: $projectName")}
return project
}
project = getProject('folder/job')
build = project.lastBuild
def checkStatus2(){
//return Jenkins.instance.getItemByFullName('folder/job').lastBuild.getResult()
return Jenkins.instance.getItemByFullName('folder/job').lastBuild.buildStatusSummary.message
}
stage('check Job A status'){
//def status = checkStatus2()
//echo status
//if(hudson.model.Result.RUNNING.equals(status)){
if(build.#result == hudson.model.Result.NOT_BUILT){
echo "running"
}else{
echo "not running"
}
}

I found a thread which gave me a hint
Jenkins workflow check if job is running or schedulled
So i tried ...
if(Jenkins.instance.getItemByFullName('folder/job').isBuilding())
... and it works.

Related

Jenkins pipeline script - stop previous build, and print message in failed build

So, I start my pipeline script with this piece of code:
node {
if (env.JOB_NAME != 'Company/project/develop' && env.JOB_NAME != 'Company/project/master'){
def jobName = env.JOB_NAME
def job = Jenkins.instance.getItemByFullName(jobName)
for (build in job.builds) {
if (build.isBuilding() && build != job.builds.first()) {
println '*' * 30
println 'All previous builds for this job have been aborted!'
println '*' * 30
build.doStop()
}}
}
}
And it works perfectly. It stops all previous builds for the same job name. The point of this is to optimize Jenkins when developers are pushing too much code, but latest push is only important one. Master and develop branches are excluded from this rule.
I would like to expand this a little bit, by adding interruption cause. I would like to print into stopped build for example: "This job has been stop because is obsolete..."
I have tried a lot of things posted on stackoverflow, but I didn't succeed.
Thanks
Here is my implementation of similar function. It will abort previous running build, and show cause "Aborted by newer build #123"
import hudson.model.Result
import hudson.model.Run
import jenkins.model.CauseOfInterruption.UserInterruption
Run previousBuild = currentBuild.rawBuild.getPreviousBuildInProgress()
while (previousBuild != null) {
if (previousBuild.isInProgress()) {
def executor = previousBuild.getExecutor()
if (executor != null) {
echo ">> Aborting older build #${previousBuild.number}"
executor.interrupt(Result.ABORTED, new UserInterruption("Aborted by newer build #${currentBuild.number}"))
}
}
previousBuild = previousBuild.getPreviousBuildInProgress()
}

Jenkins pipelines Jenkins.instance.getItemByFullName

I'm having problems with my Jenkinsfile.
I want to list all running workers in current job, but jenkins just fails without printing any error. Code snippet:
#NonCPS
def check_running_process() {
// Check if PR build already in progress to kill old one
def pull_id = env.ghprbPullId.toInteger()
println pull_id
def current_build_id = env.BUILD_ID.toInteger()
println current_build_id
def currentJob = Jenkins.instance.getItemByFullName('jobname')
println currentJob
}
Output:
[Pipeline] echo
2
[Pipeline] echo
47
So Jenkins stops at def currentJob = Jenkins.instance.getItemByFullName('jobname')
There is no error produced, just a build fail.
There are no errors in jenkins.log file.
This works in scripting console.
Did anyone had the same problem?
Thank you
Okay, this was my problem.
I was calling check_running_process() inside try handler.
This produced no error, but failed because
method jenkins.model.Jenkins getItemByFullName java.lang.String
signature was not approved
(nor it produced script approval request).

Triggering a Job on start up in Jenkins

I am trying to get a new job to run every time my Jenkins restarts. I want to do this through "init.groovy" script. For example let's say if I restart my jenkins server it will execute a job that says "Hello world". And I have to create this job from my init.groovy script.
I have this code so far
import jenkins.model.Jenkins
import org.jenkinsci.plugins.workflow.job.WorkflowJob
WorkflowJob job = Jenkins.instance.createProject(WorkflowJob, 'my-pipeline2')
now I don't know how to configure this job instance without getting into the GUI. I want to add pipeline scripts to it. Like echo "Hello world". And then I want to finally build this job. I want to do all that from this one init.groovy script. I couldn't find any solution to this over internet. So any help is greatly appreciated. Thanks
You could also try the Startup Trigger plugin.
Once installed, go the Job that you want to trigger after startup and in the section 'Build Triggers', check 'Build when Jenkins first starts'
(This question may be old, but hope my answer helps someone)
So I have finally done this with the following groovy script.
#!groovy
import jenkins.model.*
import hudson.security.*
import jenkins.install.*;
import hudson.triggers.SCMTrigger;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
def instance = Jenkins.getInstance()
println "--> creating local user 'admin'"
def hudsonRealm = new HudsonPrivateSecurityRealm(false)
hudsonRealm.createAccount('admin','admin')
instance.setSecurityRealm(hudsonRealm)
def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
instance.setAuthorizationStrategy(strategy)
instance.save()
jenkins = Jenkins.instance;
workflowJob = new WorkflowJob(jenkins, "workflow2");
jobName = "create-dsl-job2";
gitTrigger = new SCMTrigger("* * * * *");
dslProject = new hudson.model.FreeStyleProject(jenkins, jobName);
dslProject.addTrigger(gitTrigger);
jenkins.add(dslProject, jobName);
job = jenkins.getItem(jobName)
builders = job.getBuildersList()
hudson.tasks.Shell newShell = new hudson.tasks.Shell("echo \"Hello\" ")
builders.replace(newShell)
gitTrigger.start(dslProject, true);

Jenkins: remove old builds with command line

I delete old jenkins builds with rm where job is hosted:
my_job/builds/$ rm -rf [1-9]*
These old builds are still visible in job page.
How to remove them with command line?
(without the delete button in each build user interface)
Here is another option: delete the builds remotely with cURL. (Replace the beginning of the URLs with whatever you use to access Jenkins with your browser.)
$ curl -X POST http://jenkins-host.tld:8080/jenkins/job/myJob/[1-56]/doDeleteAll
The above deletes build #1 to #56 for job myJob.
If authentication is enabled on the Jenkins instance, a user name and API token must be provided like this:
$ curl -u userName:apiToken -X POST http://jenkins-host.tld:8080/jenkins/job/myJob/[1-56]/doDeleteAll
The API token must be fetched from the /me/configure page in Jenkins. Just click on the "Show API Token..." button to display both the user name and the API token.
Edit: As pointed out by yegeniy in a comment below, one might have to replace doDeleteAll by doDelete in the URLs above to make this work, depending on the configuration.
It looks like this has been added to the CLI, or is at least being worked on: http://jenkins.361315.n4.nabble.com/How-to-purge-old-builds-td385290.html
Syntax would be something like this: java -jar jenkins-cli.jar -s http://my.jenkins.host delete-builds myproject '1-7499' --username $user --password $password
Check your home jenkins directory:
"Manage Jenkins" ==> "Configure System"
Check field "Home directory" (usually it is /var/lib/jenkins)
Command for delete all jenkins job builds
/jenkins_home/jobs> rm -rf */builds/*
After delete should reload config:
"Manage Jenkins" ==> "Reload Configuration from Disk"
You can do it by Groovy Scripts using Hudson API.. Access your jenkins instalation
http://localhost:38080/script.
For Example, for deleting all old builds of all projects using the follow script:
Note: Take care if you use Finger Prints , you will lose all history.
import hudson.model.*
// For each project
for(item in Hudson.instance.items) {
// check that job is not building
if(!item.isBuilding()) {
System.out.println("Deleting all builds of job "+item.name)
for(build in item.getBuilds()){
build.delete()
}
}
else {
System.out.println("Skipping job "+item.name+", currently building")
}
}
Or for cleaning all workspaces :
import hudson.model.*
// For each project
for(item in Hudson.instance.items) {
// check that job is not building
if(!item.isBuilding()) {
println("Wiping out workspace of job "+item.name)
item.doDoWipeOutWorkspace()
}
else {
println("Skipping job "+item.name+", currently building")
}
}
There are a lot of examples on the Jenkins wiki
Is there a reason you need to do this manually instead of letting Jenkins delete old builds for you?
You can change your job configuration to automatically delete old builds, based either on number of days or number of builds. No more worrying about it or having to keep track, Jenkins just does it for you.
The following script cleans old builds of jobs. You should reload config from disk if you delete build manually:
import hudson.model.*
for(item in Hudson.instance.items) {
if (!item.isBuilding()) {
println("Deleting old builds of job " + item.name)
for (build in item.getBuilds()) {
//delete all except the last
if (build.getNumber() < item.getLastBuild().getNumber()) {
println "delete " + build
try {
build.delete()
} catch (Exception e) {
println e
}
}
}
} else {
println("Skipping job " + item.name + ", currently building")
}
}
From Script Console Run this, but you need to change the job name:
def jobName = "name"
def job = Jenkins.instance.getItem(jobName)
job.getBuilds().each { it.delete() }
job.nextBuildNumber = 1
job.save()
From Jenkins Scriptler console run the following Groovy script to delete all the builds of jobs listed under a view:
import jenkins.model.Jenkins
hudson.model.Hudson.instance.getView('<ViewName>').items.each() {
println it.fullDisplayName
def jobname = it.fullDisplayName
def item = hudson.model.Hudson.instance.getItem(jobname)
def build = item.getLastBuild()
if (item.getLastBuild() != null) {
Jenkins.instance.getItemByFullName(jobname).builds.findAll {
it.number <= build.getNumber()
}.each {
it.delete()
}
}
}
def jobName = "MY_JOB_NAME"
def job = Jenkins.instance.getItem(jobName)
job.getBuilds().findAll { it.number < 10 }.each { it.delete() }
if you had 12 builds this would clear out builds 0-9 and you'd have 12,11,10 remaining. Just drop in the script console
This script will configure the build retention settings of all of the Jenkins jobs.
Change the values from 30 and 200 to suite you needs, run the script, then restart the Jenkins service.
#!/bin/bash
cd $HOME
for xml in $(find jobs -name config.xml)
do
sed -i 's#<daysToKeep>.*#<daysToKeep>30</daysToKeep>#' $xml
sed -i 's#<numToKeep>.*#<numToKeep>200</numToKeep>#' $xml
done
The script below works well with Folders and Multibranch Pipelines. It preserves only 10 last builds for each job. That could be adjusted or removed (proper if) if needed. Run that from web script console (example URL: https://jenkins.company.com/script)
def jobs = Hudson.instance.getAllItems(hudson.model.Job.class)
for (job in jobs){
println(job)
def recent = job.builds.limit(10)
for(build in job.builds){
if(!recent.contains(build)){
println("\t Deleting build: " + build)
build.delete()
}
}
}
From my opinion all those answers are not sufficient, you have to do:
echo "Cleaning:"
echo "${params.PL_JOB_NAME}"
echo "${params.PL_BUILD_NUMBER}"
build_number = params.PL_BUILD_NUMBER as Integer
sleep time: 5, unit: 'SECONDS'
wfjob = Jenkins.instance.getItemByFullName(params.PL_JOB_NAME)
wfjob.getBuilds().findAll { it.number >= build_number }.each { it.delete() }
wfjob.save()
wfjob.nextBuildNumber = build_number
wfjob.save()
wfjob.updateNextBuildNumber(build_number)
wfjob.save()
wfjob.doReload()
Or the job will not be correctly reset and you have to hit build until you reach next free number in the meanwhile the jenkins log will show:
java.lang.IllegalStateException: JENKINS-23152: ****/<BUILD_NUMBER> already existed;

How do I clear my Jenkins/Hudson build history?

I recently updated the configuration of one of my hudson builds. The build history is out of sync. Is there a way to clear my build history?
Please and thank you
Use the script console (Manage Jenkins > Script Console) and something like this script to bulk delete a job's build history https://github.com/jenkinsci/jenkins-scripts/blob/master/scriptler/bulkDeleteBuilds.groovy
That script assumes you want to only delete a range of builds. To delete all builds for a given job, use this (tested):
// change this variable to match the name of the job whose builds you want to delete
def jobName = "Your Job Name"
def job = Jenkins.instance.getItem(jobName)
job.getBuilds().each { it.delete() }
// uncomment these lines to reset the build number to 1:
//job.nextBuildNumber = 1
//job.save()
This answer is for Jenkins
Go to your Jenkins home page → Manage Jenkins → Script Console
Run the following script there. Change copy_folder to your project name
Code:
def jobName = "copy_folder"
def job = Jenkins.instance.getItem(jobName)
job.getBuilds().each { it.delete() }
job.nextBuildNumber = 1
job.save()
My post
If you click Manage Hudson / Reload Configuration From Disk, Hudson will reload all the build history data.
If the data on disk is messed up, you'll need to go to your %HUDSON_HOME%\jobs\<projectname> directory and restore the build directories as they're supposed to be. Then reload config data.
If you're simply asking how to remove all build history, you can just delete the builds one by one via the UI if there are just a few, or go to the %HUDSON_HOME%\jobs\<projectname> directory and delete all the subdirectories there -- they correspond to the builds.
Afterwards restart the service for the changes to take effect.
Here is another option: delete the builds with cURL.
$ curl -X POST http://jenkins-host.tld:8080/jenkins/job/myJob/[1-56]/doDeleteAll
The above deletes build #1 to #56 for job myJob.
If authentication is enabled on the Jenkins instance, a user name and API token must be provided like this:
$ curl -u userName:apiToken -X POST http://jenkins-host.tld:8080/jenkins/job/myJob/[1-56]/doDeleteAll
The API token must be fetched from the /me/configure page in Jenkins. Just click on the "Show API Token..." button to display both the user name and the API token.
Edit: one might have to replace doDeleteAll by doDelete in the URLs above to make this work, depending on the configuration or the version of Jenkins used.
Here is how to delete ALL BUILDS FOR ALL JOBS...... using the Jenkins Scripting.
def jobs = Jenkins.instance.projects.collect { it }
jobs.each { job -> job.getBuilds().each { it.delete() }}
You could modify the project configuration temporarily to save only the last 1 build, reload the configuration (which should trash the old builds), then change the configuration setting again to your desired value.
If you want to clear the build history of MultiBranchProject (e.g. pipeline),
go to your Jenkins home page → Manage Jenkins → Script Console and run the following script:
def projectName = "ProjectName"
def project = Jenkins.instance.getItem(projectName)
def jobs = project.getItems().each {
def job = it
job.getBuilds().each { it.delete() }
job.nextBuildNumber = 1
job.save()
}
This one is the best option available.
Jenkins.instance.getAllItems(AbstractProject.class).each {it -> Jenkins.instance.getItemByFullName(it.fullName).builds.findAll { it.number > 0 }.each { it.delete() } }
This code will delete all Jenkins Job build history.
Using Script Console.
In case the jobs are grouped it's possible to either give it a full name with forward slashes:
getItemByFullName("folder_name/job_name")
job.getBuilds().each { it.delete() }
job.nextBuildNumber = 1
job.save()
or traverse the hierarchy like this:
def folder = Jenkins.instance.getItem("folder_name")
def job = folder.getItem("job_name")
job.getBuilds().each { it.delete() }
job.nextBuildNumber = 1
job.save()
Deleting directly from file system is not safe. You can run the below script to delete all builds from all jobs ( recursively ).
def numberOfBuildsToKeep = 10
Jenkins.instance.getAllItems(AbstractItem.class).each {
if( it.class.toString() != "class com.cloudbees.hudson.plugins.folder.Folder" && it.class.toString() != "class org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject") {
println it.name
builds = it.getBuilds()
for(int i = numberOfBuildsToKeep; i < builds.size(); i++) {
builds.get(i).delete()
println "Deleted" + builds.get(i)
}
}
}
Go to "Manage Jenkins" > "Script Console"
Run below:
def jobName = "build_name"
def job = Jenkins.instance.getItem(jobName)
job.getBuilds().each { it.delete() }
job.save()
Another easy way to clean builds is by adding the Discard Old Plugin at the end of your jobs. Set a maximum number of builds to save and then run the job again:
https://wiki.jenkins-ci.org/display/JENKINS/Discard+Old+Build+plugin
Go to the %HUDSON_HOME%\jobs\<projectname> remove builds dir and remove lastStable, lastSuccessful links, and remove nextBuildNumber file.
After doing above steps go to below link from UI
Jenkins-> Manage Jenkins -> Reload Configuration from Disk
It will do as you need
If using the Script Console method then try using the following instead to take into account if jobs are being grouped into folder containers.
def jobName = "Your Job Name"
def job = Jenkins.instance.getItemByFullName(jobName)
or
def jobName = "My Folder/Your Job Name
def job = Jenkins.instance.getItemByFullName(jobName)
Navigate to: %JENKINS_HOME%\jobs\jobName
Open the file "nextBuildNumber" and change the number. After that reload Jenkins configuration. Note: "nextBuildNumber" file contains the next build no that will be used by Jenkins.
Tested on jenkins 2.293 over linux. It will remove all the build logs but not the corellative build number
cd /var/lib/jenkins/jobs
find . -name "builds" -exec rm -rf {} \;
Be careful with this command because it executes a rm -rf on each find result. You could exec this first to validate if the result are only the builds folder of you jobs
find . -name "builds"
If you are looking for a solution where you have job inside a Folder you can use getItemByFullName function. It also supports white space in folder and job name.
def jobName = "folder_name/job_name"
def job = Jenkins.instance.getItemByFullName(jobName)
job.getBuilds().each { it.delete() }
job.nextBuildNumber = 1
job.save()

Resources