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

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

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