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

13 comments

Craig Castle-Mead
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 3, 2019

Hey Gonchik,

Great work on both parts of your articles - will be trying them out.

Wondering if you may consider a part 3 with any of the following:

- removing users/groups from a project role where that role does nothing (no permissions, notifications, use in workflow conditions etc)

- identifying use of groups (if a group is to be deprecated or renamed etc). There’s so many locations used within core/software/JSD, let alone the marketplace apps

 

CCM

Tom Lister
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
February 9, 2019

Hi @Gonchik Tsymzhitov

this could save me many hours as I’ve inherited a Jira instance at my new job with dozens and dozens of orphaned schemes.

will definitely be looking into open source groovy runners too.

Like Gonchik Tsymzhitov likes this
Gonchik Tsymzhitov
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
February 9, 2019

Hi @Tom Lister

I am happy if it helps you and feel free fork and time to time provide Pull Request:))

 

Cheers,

Gonchik Tsymzhitov

Tom Lister
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
February 13, 2019

Hi

In 4. Cleanup Un Associated Issue Type Screen

I had to change this line 

def schemeManager = ComponentAccessor.issueTypeScreenSchemeManager

Like Gonchik Tsymzhitov likes this
Tom Lister
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
February 13, 2019

Ignore the above, versions in github are good

Like Gonchik Tsymzhitov likes this
Deleted user March 4, 2019

After reading Part 1, I had to find the other.  I've bookmarked both articles for future reference.  Thank you for sharing!

Like Gonchik Tsymzhitov likes this
Gonchik Tsymzhitov
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
March 31, 2019

Welcome to use it :) 

Ahmed Trabelsi April 26, 2019

Hi @Gonchik Tsymzhitov 

Thanks for sharing scripts :)

I need to do the same for Confluence, any idea?

Like Gonchik Tsymzhitov likes this
PK_KP March 28, 2020

Hi @Gonchik Tsymzhitov 

 

Could you please provide a script to remove the  inactive status in jira, i tried a lot but it doesn't seems to be working as expected.

Thanks

Gonchik Tsymzhitov
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
May 6, 2021

@Ahmed Trabelsi Yes, I will add a few things into repo

Gonchik Tsymzhitov
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
May 6, 2021

@PK_KP Please, check out the latest one from github 

Mohammed Siyad October 6, 2022

Hi @Gonchik Tsymzhitov ,

Appreciate the effort in providing the community with the part1 and 2 article. 
Is there any way we could have a cleanup for field configurations and field configuration schemes too.

Thanking in advance.

Like Gonchik Tsymzhitov likes this
Gonchik Tsymzhitov
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
October 9, 2022

Hi @Mohammed Siyad , 

Let me think about that. 

For now I don't have any actual script. 

But actual info I keep there:

https://github.com/gonchik/cleanup-scripts

Like Mohammed Siyad likes this

Comment

Log in or Sign up to comment
TAGS
AUG Leaders

Atlassian Community Events