Advanced cleanup

Clean up your Jira instance

On this page

Still need help?

The Atlassian Community is here for you.

Ask the community

Support for Server licenses ended on February 15, 2024. Discover your options.

If you have completed your basic cleanup, you can proceed to more advanced cleanup activities. To complete advanced cleanup, you'll need to run a few scripts.

Additional mandatory cleanup process

Recommended frequency: once per year

Skills required: Advanced Jira admin skills

Note: The APIs used in the scripts below might not work with your Jira version. Please make sure to use the correct API compatible with your Jira version. You may refer to our developer documentation for the complete list of the available Java APIs for different Jira versions.

Task 1: Delete any unused or inactive workflows

How do I identify what to clean up?

Use Admin Toolbox for Jira to quickly find inactive workflows.

How do I go about the cleanup?

Delete any inactive or unused workflows and their schemes from the system. Before doing so, make sure that the Validators and Post-functions are not configured with custom fields. Fewer workflows are easier to maintain and support. For more on workflows, see Working with workflows.

The best way to delete inactive workflows and workflow schemes is to get the ScriptRunner app and run the following scripts.

Please note that these feature links and 3rd party plugins are outside our Support Offerings

Start with unused workflow schemes. To delete all inactive workflow schemes, run the script below:

import com.atlassian.jira.component.ComponentAccessor

def schemeManager = ComponentAccessor.workflowSchemeManager

def sb = new StringBuffer()
sb.append("Deleted inactive workflow schemes:\n")

schemeManager.schemeObjects.each {
 try{
   if(schemeManager.getProjectsUsing(schemeManager.getWorkflowSchemeObj(it.id)).size() == 0) {
     schemeManager.deleteScheme(it.id)
     sb.append("${it.name}\n")
   }
 }
 catch(Exception e) {
   //noop
   sb.append("Error: " + e + "\n");
 }
}

return "<pre>" + sb.toString() + "<pre>"

To delete unused or inactive workflows, run the following script:

import com.atlassian.jira.component.ComponentAccessor

def workflowManager = ComponentAccessor.workflowManager
def schemeManager = ComponentAccessor.workflowSchemeManager

def sb = new StringBuffer()
sb.append("Deleted inactive workflows:\n")

workflowManager.workflows.each {
    if(!it.systemWorkflow) {
        def schemes = schemeManager.getSchemesForWorkflow(it)
        if (schemes.size() == 0) {
            workflowManager.deleteWorkflow(it)
            sb.append("${it.name}\n")
        }
    }
}

return "<pre>" + sb.toString() + "<pre>"

Task 2: Delete unused screens and screen schemes

How do I identify what to clean up?

The ScriptRunner app will help you identify and delete unused screens and screen schemes. Config Insights for Jira that will help you visualize relationships between various Jira artifacts.

It's a good idea not to delete the default screen schemes and default screens.

How do I go about the cleanup?

  1. Delete all Issue Type Screen Schemes without any associated projects:


import com.atlassian.jira.component.ComponentAccessor

def schemeManager = ComponentAccessor.issueTypeScreenSchemeManager
def defaultScheme = schemeManager.defaultScheme;

def sb = new StringBuffer()

sb.append("Deleted issue type screen schemes with no associated projects:\n")

schemeManager.issueTypeScreenSchemes.each {
 try{
  if(it == defaultScheme) {
   //do not delete the default scheme
   return;
  }

  if(it.projects.size() == 0) {
   //remove any associations with screen schemes
   schemeManager.removeIssueTypeSchemeEntities(it);

   //remove the issue type screen scheme 
   schemeManager.removeIssueTypeScreenScheme(it);
   sb.append("${it.name}\n")
  }
 }
 catch(Exception e) {
  //noop
  sb.append("Error: " + e + "\n");
 }
}

return "<pre>" + sb.toString() + "<pre>"


2. Delete Screen Schemes not used by any Issue Type Screen Schemes, or only used by deleted Issue Type Screen Schemes.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.fields.screen.FieldScreenSchemeManager

def fssm = ComponentAccessor.getComponent(FieldScreenSchemeManager.class)
def itssm = ComponentAccessor.issueTypeScreenSchemeManager

def sb = new StringBuffer()

sb.append("Deleted screen schemes with no associated issue type screen schemes:\n")

fssm.fieldScreenSchemes.each { fss ->
 try {
  def itssCollection = itssm.getIssueTypeScreenSchemes(fss);

  // find field screen schemes that are still associated with deleted issues type screen schemes
  def allDeleted = true;
  itssCollection.each { itss ->
   if(itss != null) {
    allDeleted = false;
    return;
   } 
  }

  //remove field screen schemes with no (valid) associated issue type screen schemes
  if(itssCollection.size() == 0 || allDeleted == true) {
   //remove association to any screens
   fssm.removeFieldSchemeItems(fss);
   //remove field screen scheme
   fssm.removeFieldScreenScheme(fss);
   sb.append("${fss.name}\n");
  }

 }
 catch(Exception e) {
  //noop
  sb.append("Error: " + e + "\n");
 }
}

return "<pre>" + sb.toString() + "<pre>"


3. Delete unused screens. Note that the code differs, depending on your Jira version:

If you're using Jira 8.20 or later, run the code below.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.fields.screen.FieldScreenFactory
import com.atlassian.jira.issue.fields.screen.FieldScreenManager
import com.atlassian.jira.issue.fields.screen.FieldScreenSchemeManager
import com.atlassian.jira.bc.issue.fields.screen.FieldScreenService
import com.atlassian.jira.web.action.admin.issuefields.screens.ViewFieldScreens
import com.atlassian.jira.workflow.WorkflowManager
import com.atlassian.webresource.api.assembler.PageBuilderService

def fieldScreenManager = ComponentAccessor.getFieldScreenManager()
def fieldScreenFactory = ComponentAccessor.getComponent(FieldScreenFactory.class)
def fieldScreenSchemeManager = ComponentAccessor.getComponent(FieldScreenSchemeManager.class)
def fieldScreenService = ComponentAccessor.getComponent(FieldScreenService.class)
def workflowManager = ComponentAccessor.getWorkflowManager()
def authenticationContext = ComponentAccessor.getJiraAuthenticationContext()
def pageBuilderService = ComponentAccessor.getComponent(PageBuilderService.class)

def viewFieldScreens = new ViewFieldScreens(fieldScreenManager, fieldScreenFactory, fieldScreenSchemeManager, fieldScreenService,
  workflowManager, authenticationContext, pageBuilderService)

// use StringBuffer to spit out log to screen for ScriptRunner Console
def sb = new StringBuffer()

sb.append("Delete unused screens:\n");

fieldScreenManager.getFieldScreens().each {
  fieldScreen ->

    //find all screens with no (or only null/previously deleted) screen schemes or workflows
    def allEmptyOrNull = true;

  viewFieldScreens.getFieldScreenSchemes(fieldScreen).each {
    fieldScreenScheme ->
      if (fieldScreenScheme != null) {
        allEmptyOrNull = false;
        return;
      }
  }

  if (!allEmptyOrNull) {
    return;
  }

  viewFieldScreens.getWorkflows(fieldScreen).each {
    workflow ->
      if (workflow != null) {
        allEmptyOrNull = false;
        return;
      }
  }

  if (allEmptyOrNull) {
    fieldScreenManager.removeFieldScreen(fieldScreen.getId())
    sb.append("${fieldScreen.getName()}\n")
  }

}

return "<pre>" + sb.toString() + "<pre>"

If you're using a version earlier than Jira 8.20, run the code below.

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.fields.screen.FieldScreenFactory
import com.atlassian.jira.issue.fields.screen.FieldScreenManager
import com.atlassian.jira.issue.fields.screen.FieldScreenSchemeManager
import com.atlassian.jira.web.action.admin.issuefields.screens.ViewFieldScreens
import com.atlassian.jira.workflow.WorkflowManager

def fieldScreenManager = ComponentAccessor.getFieldScreenManager()
def fieldScreenFactory = ComponentAccessor.getComponent(FieldScreenFactory.class)
def fieldScreenSchemeManager = ComponentAccessor.getComponent(FieldScreenSchemeManager.class)
def workflowManager = ComponentAccessor.getWorkflowManager()
def viewFieldScreens = new ViewFieldScreens(fieldScreenManager, fieldScreenFactory, fieldScreenSchemeManager, workflowManager)

// use StringBuffer to spit out log to screen for ScriptRunner Console
def sb = new StringBuffer()

sb.append("Delete unused screens:\n");

fieldScreenManager.getFieldScreens().each { fieldScreen ->

 //find all screens with no (or only null/previously deleted) screen schemes or workflows
 def allEmptyOrNull = true;

 viewFieldScreens.getFieldScreenSchemes(fieldScreen).each { fieldScreenScheme ->
  if(fieldScreenScheme != null) {
   allEmptyOrNull = false;
   return;
  }
 }

 if(!allEmptyOrNull) {
  return;
 }

 viewFieldScreens.getWorkflows(fieldScreen).each { workflow ->
  if(workflow != null) {
   allEmptyOrNull = false;
   return;
  }
 }

 if(allEmptyOrNull) {
  fieldScreenManager.removeFieldScreen(fieldScreen.getId())
  sb.append("${fieldScreen.getName()}\n")
 }

}


return "<pre>" + sb.toString() + "<pre>"

Task 3: Review resolutions

Resolutions in Jira are shared globally—consolidating them whenever possible will reduce clutter.

How do I identify what to clean up?

Run a JQL query such as "Resolution = 'whatever'" to find how many issues (if any) use a particular resolution.

You can also create an issue statistics gadget grouping a JQL query by Resolution. For more on gadgets, see Using dashboards gadgets.

How do I go about the cleanup?

From the Resolutions page in the administration panel, click Delete on the resolution you wish to get rid of. Jira will tell you how many issues currently have that resolution and also ask you to pick a different resolution from the list for those issues.

Task 4: Clean up field configurations

Field Configuration tells Jira which fields are available to each Project (and Issuetype). Even if the fields aren't present in any screen, they are considered in the reindex process.

By default, Jira adds every newly created custom field to all Field Configurations available. So the performance might decline if you have a lot of custom fields. 

How do I identify what to clean up?

For this task, you don't have to delete things, but hide the custom fields and enable only the ones you want for a project. So, this is a fairly safe way of cleaning up.

Make sure these fields are always enabled for your projects: Assignee, Attachment, Description, Due Date, Labels, Log Work, Priority, Reporter, Resolution, and Time Tracking.

How do I go about the cleanup?

Create an "empty" Field Configuration (FC) with no fields associated with it. Use it as a template, and add all your custom fields to this configuration, and disable those. When you create new projects, you can enable only the desired fields you want to use in these projects (or issue types). 

Next use the ScriptRunner app and run the following script. It will make all custom fields in a particular Field Configuration hidden, which, in turn, will make them invisible and not editable in all Projects that use that field configuration.

 Replace "18000L" with your own FC.
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.fields.layout.field.FieldLayoutManager
import com.atlassian.jira.issue.fields.layout.field.EditableFieldLayout
import com.atlassian.jira.issue.fields.layout.field.FieldLayoutItem

FieldLayoutManager fieldConfigurationManager = ComponentAccessor.getComponent(FieldLayoutManager)
EditableFieldLayout fieldConfiguration = fieldConfigurationManager.getEditableFieldLayout(18000L)
List<FieldLayoutItem> items = fieldConfiguration.getFieldLayoutItems()

items.each {
 try {
 fieldConfiguration.hide(it)
 } catch (ignored) {}
}

fieldConfigurationManager.storeEditableFieldLayout(fieldConfiguration)


Task 5: Audit your apps

Uninstalling unused apps will help keep your Jira from using unnecessary RAM, keep your marketplace costs down, and save you time upgrading them to newer versions.

How do I identify what to clean up?

Unfortunately, apps vary widely in the way they work, and it's not really possible to determine how they're getting used in a one-size-fits-all approach.

The best idea is to manually check each app for usage.


Need app assistance?

It’s hard to find a one-fit all app, however, to analyze your workflow plugins, Admin Toolbox for Jira might help.

How do I go about the cleanup?

Disable the apps with low usage and/or the ones you have doubts about in the test environment and observe the outcomes.

How do I automate?

For each of the tasks, it's a good idea to monitor for new entities being created (Advanced audit log can help here) and run regular reviews. 

(tick) All good? Now, see how you can optimize your data management process


Last modified on May 15, 2024

Was this helpful?

Yes
No
Provide feedback about this article
Powered by Confluence and Scroll Viewport.