Continuous cleanup for Jira. Part 2.

 Hi awesome community! 

 

This is the second iteration from series of article about Continuous Jira cleanup which I have tried to implement automation scripts for my Jira instance. (first one here)

Today, I would like to share a few scripts related to clean up configuration of the project. 

 

Disclaimer,  as usual, everything should be tested in the test-environment first.

Also, I'll be happy if you share or provide advice for the related small scripts. All scripts were tested and executed on Jira 7 Server releases (7.6.10, 7.13.0).

Well, you can use for execute groovy on Jira one of these apps (add-ons) - Scriptrunner for Jira (commercial) , MyGroovy (Opensource BSD-2) , Groovioli (Opensource BSD-2)

 

And scripts based on this scheme

image.png

 

Well, let's next step is cleanup our Jira instance.

 

1. Cleanup UnAssociated Issue Type

boolean isPreview = true

import
com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.config.IssueTypeManager
import org.apache.log4j.Logger
import org.apache.log4j.Level

def log = Logger.getLogger("com.gonchik.scripts.groovy.cleanupUnAssociatedIssueType")
log.setLevel(Level.DEBUG)

// Cleanup of the cleanupUnAssociatedIssueType
def issueTypeManager = ComponentAccessor.getComponent(IssueTypeManager)
def sb = new StringBuilder()

sb.append("Deleted issue type schemes with no associated projects:<br/><br/>\n")
issueTypeManager.issueTypes.each {
try {
if (!issueTypeManager.hasAssociatedIssues(it)) {
sb.append("${it.name}<br/>\n")
if (!isPreview) {
// Set the Default of Task Id
String replaceIssueTypeId = "1"
if (it.isSubTask()){
// Id of Sub-Task
replaceIssueTypeId = "5"
}
issueTypeManager.removeIssueType(it.id, replaceIssueTypeId)
}
}
}
catch (Exception e) {
sb.append("Error: " + e + "<br/>\n")
}
}

return sb.toString()

 

2. Cleanup unused Issue Type Schemes.

boolean isPreview = false
import com.atlassian.jira.component.ComponentAccessor
import org.apache.log4j.Logger
import org.apache.log4j.Level

def log = Logger.getLogger("com.gonchik.scripts.groovy.cleanupUsUsedIssueTypeSchemes")
log.setLevel(Level.DEBUG)

def schemeManager = ComponentAccessor.issueTypeSchemeManager
def sb = new StringBuilder()

sb.append("Deleted issue type schemes with no associated projects:<br/><br/>\n")
schemeManager.allSchemes.each {
if (schemeManager.isDefaultIssueTypeScheme(it)){
return
}
try {
if (it.associatedProjectIds.size() == 0) {
sb.append("${it.name}<br/>\n")
if (!isPreview) {
schemeManager.deleteScheme(it)
}
}
}
catch (Exception e) {
sb.append("Error: " + e + "<br/>\n")
}
}

return sb.toString()

 

3. Cleanup Issue Type Screen Schemes.

boolean isPreview = true
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.fields.screen.issuetype.IssueTypeScreenSchemeManager
import org.apache.log4j.Logger
import org.apache.log4j.Level

def log = Logger.getLogger("com.gonchik.scripts.groovy.cleanupUsUsedIssueTypeScreenManager")
log.setLevel(Level.DEBUG)

def schemeManager = ComponentAccessor.issueTypeScreenSchemeManager
def sb = new StringBuilder()

sb.append("Deleted issue type screen schemes with no associated projects:<br/><br/>\n")
schemeManager.issueTypeScreenSchemes.each {
if (it.isDefault()) {
return
}
try {
if (schemeManager.getProjects(it).size() < 1) {
sb.append("${it.name}<br/>\n")
if (!isPreview) {
schemeManager.removeIssueTypeScreenScheme(it)
}
}
}
catch (Exception e) {
sb.append("Error: " + e + "<br/>\n")
}
}

return sb.toString()

 

4. Cleanup Un Associated Issue Type Screen

boolean isPreview = true

import
com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.fields.screen.issuetype.IssueTypeScreenSchemeManager
import org.apache.log4j.Logger
import org.apache.log4j.Level

def log = Logger.getLogger("com.gonchik.scripts.groovy.cleanupUnAssociatedIssueTypeScreen")
log.setLevel(Level.DEBUG)

def schemeManager = ComponentAccessor.issueTypeScreenManager
def sb = new StringBuilder()

sb.append("Deleted issue type screen schemes with no associated projects:<br/><br/>\n")
schemeManager.issueTypeScreenSchemes.each {
if (it.isDefault()) {
return
}
try {
if (schemeManager.getProjects(it).size() == 0) {
sb.append("${it.name}<br/>\n")
if (!isPreview) {
schemeManager.removeIssueTypeScreenScheme(it)
}
}
}
catch (Exception e) {
sb.append("Error: " + e + "<br/>\n")
}
}

return sb.toString()

 

5. Cleanup unused Field Screens.

boolean isPreview = true

import
com.atlassian.jira.component.ComponentAccessor
import org.apache.log4j.Logger
import org.apache.log4j.Level

def log = Logger.getLogger("com.gonchik.scripts.groovy.cleanupUnUsedFieldScreens")
log.setLevel(Level.DEBUG)

def schemeManager = ComponentAccessor.fieldScreenSchemeManager
def sb = new StringBuilder()

sb.append("Deleted issue type screen schemes with no associated projects:<br/><br/>\n")
schemeManager.fieldScreenSchemes().each {
if (it.isDefault()) {
return
}
try {
if (schemeManager.getProjects(it).size() == 0) {
sb.append("${it.name}<br/>\n")
if (!isPreview) {
schemeManager.removeFieldScreenScheme(it)
}
}
}
catch (Exception e) {
sb.append("Error: " + e + "<br/>\n")
}
}

return sb.toString()

 

 

 

And last one is cleanup un associated workflow schemes and workflows:

boolean isPreview = true
import com.atlassian.jira.component.ComponentAccessor
import org.apache.log4j.Logger
import org.apache.log4j.Level


def log = Logger.getLogger("com.gonchik.scripts.groovy.deleteUnUsedWorkflows")
log.setLevel(Level.DEBUG)

def workflowManager = ComponentAccessor.workflowManager
def schemeManager = ComponentAccessor.workflowSchemeManager
def sb = new StringBuilder()

// Review workflow schemes
schemeManager.schemeObjects.each {
try {
if (schemeManager.getProjectsUsing(schemeManager.getWorkflowSchemeObj(it.id)).size() == 0) {
sb.append("${it.name}<br/>\n")
if (!isPreview) {
log.info("Deleting workflow scheme: ${it.name}")
schemeManager.deleteScheme(it.id)
}
}
}
catch (Exception e) {
log.error('Something wrong, ' + e)
sb.append("Error: " + e + "<br/>\n")
}
}

// review Workflows
workflowManager.workflows.each {
if (!it.systemWorkflow) {
def schemes = schemeManager.getSchemesForWorkflow(it)
if (schemes.size() == 0) {
sb.append("${it.name}<br/>\n")
if (!isPreview) {
log.info("Deleting workflow: ${it.displayName}")
workflowManager.deleteWorkflow(it)
}
}
}
}

return sb.toString()

  

I hope these short scripts will reduce your manual work.

Have a nice experiments. :)

P.S. All related code you can find bitbucket repo or github repo

P.S.S Next article will related to the comparing the configs. 

P.S.S.S. After that I will show how to find same configs with predefined distance of next configs. (Levenshtein distance)  

 

Cheers,

Gonchik Tsymzhitov

Comments

Popular posts from this blog

How only 2 parameters of PostgreSQL reduced anomaly of Jira Data Center nodes

Atlassian Community, let's collaborate and provide stats to vendors about our SQL index usage

Stories about detecting Atlassian Confluence bottlenecks with APM tool [part 1]