How to delete multiple jobs?

Issue

You would like to delete multiple jobs simultaneously in folders, delete multiple jobs of a certain type or block certain job types from being created on your Master.

Environment

Resolution

1. If you would like to block certain Job types from being created in Jenkins the recommended way is to use Folders from the Folders Plugin. Using these folders you should configure Users into Groups and give these groups Roles that allow for them to only create and run jobs in specific folders meant for these Groups.

Then you may select Configure on these folders, go to the bottom of that page where you see a checkbox, Restrict the kind of children in this folder select this checkbox and you may now select the specific kinds of jobs you would like to allow within this folder.

The image example below shows how to restrict a Group’s folder to not being able to create a FreeStyle Job:

RestrictFolderJobs.png

NOTE: There is no undo for any Groovy Scripts once they have been ran and the jobs are deleted. It is always heavily recommended to take a backup before deleting anything or running any Groovy Scripts on your Jenkins instance.

2. To delete a set of specific Jobs by name you can run the following Groovy Script from the Script Console ($JENKINS_URL/script):

import hudson.model.*

jobsToDelete = ["aFolder/aJobInFolder","topLevelJob"]

deleteChildren(Hudson.instance.items)

def deleteChildren(items) {
  items.each { item ->
    if (item.class.canonicalName != 'com.cloudbees.hudson.plugins.folder.Folder') {
      if (jobsToDelete.contains(item.fullName)) {
        println(item.fullName)
        //item.delete()
      }
    } else {
    deleteChildren(((com.cloudbees.hudson.plugins.folder.Folder) item).getItems())
    }
  }
}

Replace jobsToDelete values with your job names. Note that for jobs in folders use / separator with folder names, i.e. aFolder/aJobInFolder.

Running with //item.delete() allows you to see a list of jobs that would be deleted without actually deleting any (dry run). Once you are happy with the job list uncomment item.delete(), i.e. //item.delete() -> item.delete().

3. If you would like to delete ALL MultiBranch Jobs then you may use the below Groovy Script from the Script Console

import jenkins.model.Jenkins
import hudson.model.Job
import org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject

//Input:
//If dryRun is true, will print list of jobs that would be included in the deletion
def dryRun = true

Jenkins.get().getAllItems(WorkflowMultiBranchProject.class).each { WorkflowMultiBranchProject job ->
  if (dryRun) {
      println "${job.fullName} will be removed."
  } else {
      job.doDisable()
      job.delete()
      println "${job.fullName} has been removed."
  }
}
return

Running with dryRun=true allows you to see a list of jobs that would be deleted without actually deleting any. Once you are happy with the job list, run with dryRun=false

WARNING Please note that this will delete ALL MultiBranch jobs in your instance, at the root and all folders and nested folders.

4. If you would like to delete ALL jobs of FreeStyle or Pipeline (WARNING This INCLUDES Pipeline Branches in MultiBranchPipeline Folders) type then you may use the below Groovy Script from the Script Console ($JENKINS_URL/script):

import jenkins.model.Jenkins
import hudson.model.Job
import hudson.model.FreeStyleProject
import org.jenkinsci.plugins.workflow.job.WorkflowJob

//Inputs:

//If dryRun is true, will print list of jobs that would be included in the deletion
def dryRun = true

//Copy one of these Job Types available for deletion: FreeStyleProject, WorkflowJob
def jobDeleteType = JOB_TYPE


//Script:
Jenkins.instance.getAllItems(Job.class)
        .findAll { Job job -> (job in jobDeleteType) }
        .each { Job job ->
            def jobName = "${jobDeleteType} Job Name: ${job.fullName}"
            if (dryRun) {
                println "${jobName} will be removed."
            } else {
                job.delete()
                println "${jobName} has been removed."
            }
        }
return

WARNING Please note that this will delete ALL jobs in your instance of this specific type, throughout the root location and all folders and nested folders.

You may use either FreeStyleProject within the jobDeleteType variable to delete all FreeStyle jobs or use WorkflowJob to delete all Pipeline Projects.

Running with dryRun=true allows you to see a list of jobs that would be deleted without actually deleting any. Once you are happy with the job list, run with dryRun=false

Have more questions?

6 Comments

  • 0
    Avatar
    Imran Khan

    Why is this line called if the item is not a folder?

    deleteChildren(((com.cloudbees.hudson.plugins.folder.Folder) item).getItems())

    edit:

    Nevermind.  I understand recursion. I swear. 

    Edited by Imran Khan
  • 0
    Avatar
    Allan Burdajewicz

    This line is in the `else {...}` block and therefore is called when the item IS a folder:

        else {
        deleteChildren(((com.cloudbees.hudson.plugins.folder.Folder) item).getItems())
        }

    The indentation is confusing though...

  • 0
    Avatar
    Luke Chalmers

    I am going to be refreshing a large number of jobs from one environment to another.  Unfortunately this had been done once in the past and the new environment wasnt used.  As a result theres a bunch of old copies of the jobs in on the new system and I am thinking I should delete them before migrating the fresh copies over.  

    1) if I copy the jobs over at the file system level and force an overwrite is that known to be problematic? 

    2) if I use this command to delete the jobs first, and I delete all jobs in a folder but that the folder is nested several layers down what would be the correct syntax? 

    i.e. 

    jobsToDelete = [Root_Folder/Sub_Folder/FolderWithOldJobs] 
    ?
  • 0
    Avatar
    Denys Digtiar

    Hi Luke,

    If you need to delete all the Projects in a Folder, you don't necessary need this script. You can just delete a folder which will delete all its content as well. You can recreate the Folder again if you still need it afterward.

  • 0
    Avatar
    Raja Gopalan

    When i run this script, i get the following error and reading further, it looks like the script only works for setups that have the CloudBees Folders Plugin. for a plain vanilla Jenkins without plugins please? 

    Result

    org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
    Script1.groovy: 15: unable to resolve class com.cloudbees.hudson.plugins.folder.Folder 
     @ line 15, column 20.
           deleteChildren(((com.cloudbees.hudson.plugins.folder.Folder) item).getItems())
                          ^
    
    1 error
    
    	at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
    	at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:958)
    	at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:605)
    	at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:554)
    	at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
    	at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
    	at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
    	at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
    	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:584)
    	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:623)
    	at groovy.lang.GroovyShell.evaluate(GroovyShell.java:594)
    	at hudson.util.RemotingDiagnostics$Script.call(RemotingDiagnostics.java:142)
    	at hudson.util.RemotingDiagnostics$Script.call(RemotingDiagnostics.java:114)
    	at hudson.remoting.LocalChannel.call(LocalChannel.java:45)
    	at hudson.util.RemotingDiagnostics.executeGroovy(RemotingDiagnostics.java:111)
    	at jenkins.model.Jenkins._doScript(Jenkins.java:4331)
    	at jenkins.model.Jenkins.doScript(Jenkins.java:4302)
    	at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
    	at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:343)
    	at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:184)
    	at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:117)
    	at org.kohsuke.stapler.MetaClass$1.doDispatch(MetaClass.java:129)
    	at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:58)
    	at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:715)
    	at org.kohsuke.stapler.Stapler.invoke(Stapler.java:845)
    	at org.kohsuke.stapler.Stapler.invoke(Stapler.java:649)
    	at org.kohsuke.stapler.Stapler.service(Stapler.java:238)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:841)
    	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1650)
    	at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:154)
    	at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:157)
    	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
    	at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:99)
    	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
    	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
    	at hudson.security.UnwrapSecurityExceptionFilter.doFilter(UnwrapSecurityExceptionFilter.java:51)
    	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    	at jenkins.security.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:117)
    	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    	at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
    	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    	at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:142)
    	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    	at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:271)
    	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    	at jenkins.security.BasicHeaderProcessor.doFilter(BasicHeaderProcessor.java:93)
    	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    	at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
    	at hudson.security.HttpSessionContextIntegrationFilter2.doFilter(HttpSessionContextIntegrationFilter2.java:67)
    	at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
    	at hudson.security.ChainedServletFilter.doFilter(ChainedServletFilter.java:90)
    	at hudson.security.HudsonFilter.doFilter(HudsonFilter.java:171)
    	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
    	at org.kohsuke.stapler.compression.CompressionFilter.doFilter(CompressionFilter.java:49)
    	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
    	at hudson.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:82)
    	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
    	at org.kohsuke.stapler.DiagnosticThreadNameFilter.doFilter(DiagnosticThreadNameFilter.java:30)
    	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
    	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533)
    	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)
    	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
    	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
    	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
    	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
    	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
    	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
    	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
    	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
    	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
    	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
    	at org.eclipse.jetty.server.Server.handle(Server.java:564)
    	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:317)
    	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
    	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
    	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:110)
    	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
    	at org.eclipse.jetty.util.thread.Invocable.invokePreferred(Invocable.java:128)
    	at org.eclipse.jetty.util.thread.Invocable$InvocableExecutor.invoke(Invocable.java:222)
    	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:294)
    	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:199)
    	at winstone.BoundedExecutorService$1.run(BoundedExecutorService.java:77)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    	at java.lang.Thread.run(Thread.java:812)
    
    Edited by Raja Gopalan
  • 0
    Avatar
    Arun Kumar

    Hi

    Help me in just deleteing the folder

Please sign in to leave a comment.