Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Next challenges

Recent achievements

  • Global
  • Personal

Recognition

  • Give kudos
  • Received
  • Given

Leaderboard

  • Global

Trophy case

Kudos (beta program)

Kudos logo

You've been invited into the Kudos (beta program) private group. Chat with others in the program, or give feedback to Atlassian.

View group

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

How to find all JIRA filters that include JQL for a custom field value

Use case: I want to remove an old custom field value (or convert the old value into a new value). 

However, I need to see if that change would cause any JIRA filters including Board Quick Filter errors.

 

 

4 answers

1 accepted

2 votes
Answer accepted

Bit late to the party, but wanted to provide an answer I'd cooked up for a similar question:

import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.search.SearchRequestEntity
import com.atlassian.jira.issue.search.SearchRequestManager
import com.atlassian.jira.util.Visitor

def filtersWithField = []
def myCustomFieldRegex = ~/(.*?Whatever You Call This Field.*?)|(.*?cf\[12345\].*?)/
def searchService = ComponentAccessor.getComponent(SearchService)
def searchRequestManager = ComponentAccessor.getComponent(SearchRequestManager)
searchRequestManager.visitAll(new Visitor<SearchRequestEntity>() {
@Override
void visit(SearchRequestEntity filter) {
def jql = filter.request
if (jql.findAll(myCustomFieldRegex)) {
/*
You don't have to get the search request object
as I am doing here. However, if you want to programatically
update search requests, you'll need to get the SearchRequest object itself, as I'm doing here. The SearchRequestEntity is a bit quicker to get, so I'm using that for this loop that iterates through the
entire list of saved filters.
*/
filtersWithField << searchRequestManager.getSearchRequestById(filter.id)
}
}
})
log.warn filtersWithField

You'll need to tweak the regular expression in the second line of code to match your custom field. Note that I've accounted for both the case where someone uses the custom field name in a query and where they reference it by ID.

The main difference between this and Daniel's is that instead of looping through the users and checking their owned filters, this uses the SearchRequestManager to loop through all saved searches directly.

I'm pretty sure the quick filters used on Jira Software Boards require their own treatment, but see the examples at https://scriptrunner.adaptavist.com/latest/jira/plugins/working-with-jira-agile.html for a starting point on looping through boards.

The following groovy script (run it in scriptrunner console) should help

 

import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.bc.filter.SearchRequestService
import com.atlassian.jira.issue.search.SearchRequest
import com.atlassian.jira.bc.user.search.UserSearchParams
import com.atlassian.jira.bc.user.search.UserSearchService
import java.lang.StringBuilder

// Change these 2 constants to the values you want to search for
Integer CUSTOM_FIELD_ID = 12345
String CUSTOM_FIELD_NAME = 'My Custom Field'


SearchRequestService searchRequestService = ComponentAccessor.getComponent(SearchRequestService.class)
UserSearchService userSearchService = ComponentAccessor.getComponent(UserSearchService)
StringBuilder output = StringBuilder.newInstance()
output << "<pre>\n"

UserSearchParams userSearchParams = new UserSearchParams.Builder()
    .allowEmptyQuery(true)
    .ignorePermissionCheck(true)
    .maxResults(10000)
    .build()
userSearchService.findUsers("", userSearchParams).each{ApplicationUser filter_owner ->
    searchRequestService.getOwnedFilters(filter_owner).each{SearchRequest filter->
        String jql = filter.getQuery().toString()
        if (jql.contains(CUSTOM_FIELD_NAME) || jql.contains("cf[${CUSTOM_FIELD_ID}]")) {
            output << "${filter_owner.displayName}, ${filter.name}, ${filter.getPermissions().isPrivate() ? 'Private' : 'Shared'}, ${jql}\n"
        }
    }
}

output << "</pre>"
output.toString()

It isn't perfect as it would also match filters with your field name in search string (e.g. description ~ "my custom field is awesome") but for most purposes it should do what you want

I receive an error when attempting to run that script:

ScriptConsole.jpg

I was able to execute the following script (via Jonny Carter):

import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.search.SearchRequestEntity
import com.atlassian.jira.issue.search.SearchRequestManager
import com.atlassian.jira.util.Visitor

def filtersWithField = []
def myCustomFieldRegex = ~/(.*?Whatever You Call This Field.*?)|(.*?cf\[12345\].*?)/
def searchService = ComponentAccessor.getComponent(SearchService)
def searchRequestManager = ComponentAccessor.getComponent(SearchRequestManager)
searchRequestManager.visitAll(new Visitor<SearchRequestEntity>() {
    @Override
    void visit(SearchRequestEntity filter) {
        def jql = filter.request
        if (jql.findAll(myCustomFieldRegex)) {
            /*
            You don't have to get the search request object
            as I am doing here. However, if you want to programatically
            update search requests, you'll need to get the SearchRequest object itself, as I'm doing here. The SearchRequestEntity is a bit quicker to get, so I'm using that for this loop that iterates through the
            entire list of saved filters.
             */
            filtersWithField << searchRequestManager.getSearchRequestById(filter.id)
        }
    }
})
log.warn filtersWithField

However, it appears to only scan system-based filters.  Is it also possible to scan board quick filters too?

It looks like a permission problem to me

This version should be more robust and will display what it can. It will also tell you which users it is having trouble with

import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.bc.filter.SearchRequestService
import com.atlassian.jira.issue.search.SearchRequest
import com.atlassian.jira.bc.user.search.UserSearchParams
import com.atlassian.jira.bc.user.search.UserSearchService
import java.lang.StringBuilder

// Change these 2 constants to the values you want to search for
Integer CUSTOM_FIELD_ID = 12345
String CUSTOM_FIELD_NAME = 'Field name'


SearchRequestService searchRequestService = ComponentAccessor.getComponent(SearchRequestService.class)
UserSearchService userSearchService = ComponentAccessor.getComponent(UserSearchService)
StringBuilder output = StringBuilder.newInstance()
output << "<pre>\n"

UserSearchParams userSearchParams = new UserSearchParams.Builder()
    .allowEmptyQuery(true)
    .ignorePermissionCheck(true)
    .maxResults(10000)
    .build()
userSearchService.findUsers("", userSearchParams).each{ApplicationUser filter_owner ->
    try {
        searchRequestService.getOwnedFilters(filter_owner).each{SearchRequest filter->
            String jql = filter.getQuery().toString()
            if (jql.contains(CUSTOM_FIELD_NAME) || jql.contains("cf[${CUSTOM_FIELD_ID}]")) {
                output << "${filter_owner.displayName}, ${filter.name}, ${filter.getPermissions().isPrivate() ? 'Private' : 'Shared'}, ${jql}\n"
            }
        }
    } catch (Exception e) {
           output << "Unable to get filters for ${filter_owner.displayName} due to ${e}"     
    }
}

output << "</pre>"
output.toString()

Others may know, but we needed this capability for Components and the simple change worked great:

if (jql.contains(CUSTOM_FIELD_NAME) || jql.contains("cf[${CUSTOM_FIELD_ID}]"))

to 

if (jql.contains('component/s') || jql.contains("component entry")) {

 We are using JIRA v7.4.4 and Script Runner v5.3.5, 

For anyone still interested in this functionality:

The Subscriptions for Jira app allows Jira admin to find all filters by a piece of JQL (almost like a regular text search but within JQL-queries).

Is there any way to do this without having scriptrunner? Or does anyone know of a feature request submitted to Atlassian for this ability?

Suggest an answer

Log in or Sign up to answer
TAGS

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you