2
1
0

JIRAのフィルター名の一括変更は可能でしょうか。

フィルター名の一部を変更したいのですが、数が多く困ってます。
ある程度規則性はあるので、一括置換の変更があればお力を貸してください。

    Commentコメントを追加...

    2 回答

    1.  
      4
      3
      2

      通常、フィルター名の一括変更は不可能です。

       

      できる範囲として自分がオーナになっているフィルターであれば、画面からフィルター名を変更できます。

      https://confluence.atlassian.com/jirasoftwareserver073/saving-your-search-as-a-filter-861256242.html

      一括という意味ではこの範囲でよければ REST API でもできるかもしれないですが... 

      https://docs.atlassian.com/jira/REST/server/#api/2/filter-editFilter

       

      共有フィルターについてはJIRA管理者であれば管理画面からオーナーを変更して、そのうえでフィルター名を変更することができます。

      https://confluence.atlassian.com/jirakb/how-to-rename-a-shared-filter-in-jira-777008176.html

       

      唯一画面から変更できないのは、共有していないプライベートフィルターですね…

      とはいえ、たとえ全部変更できたとしても画面から一つずつ変更する必要があります…

       

      一括という方法としてはDBかアドオン開発 or ScriptRunner なりを使ってスクリプトを作るかで変更はできると思います。

      DBの場合は searchrequest テーブルを修正するか(JIRAの再起動が必要になります)

      ScriptRunner のスクリプトとしては以下のような感じですかね…

      /**** 設定値開始  ****/
      
      /* 実際に置換をせずチェックをしたい場合:true, 置換をしたい場合:false  */
      boolean isDryrun = true;
      
      /* 正規表現で検索したい場合:true、検索文字列が正規表現ではない:false */
      boolean isRegexSearch = false;
      
      /* 例:kengo という文字列を検索してヒットしたものを ohsaki に置換 */
      String searchString  = "kengo";
      String replaceString = "ohsaki";
      
      /* 置換から除外したいフィルターIDがある場合指定フィルターIDのLong値をaddで追加していく */
      java.util.List<Long> excludeList = new java.util.ArrayList<Long>();
      
      /**** 設定値終了 ****/
      
      /* 以降置換処理 */
      log.error(String.format("REPALCE START(dryRun: %s)", isDryrun));
      
      /* 各種マネジャーオブジェクト取得 */
      com.atlassian.jira.issue.search.SearchRequestManager searchRequestManager = com.atlassian.jira.component.ComponentAccessor.getComponent(com.atlassian.jira.issue.search.SearchRequestManager.class);
      
      
      /* JIRAに登録されている全てのフィルターを取得 */
      final com.atlassian.jira.util.collect.EnclosedIterable<com.atlassian.jira.issue.search.SearchRequest> searchRequestIterable = searchRequestManager.getAll();
      if (searchRequestIterable == null) {
      	log.error("ERROR(searchRequestManager.getAll): !!NULL ERROR!!");
      	return;
      }
      final java.util.Collection<com.atlassian.jira.issue.search.SearchRequest> searchRequestCollection = com.atlassian.jira.util.collect.EnclosedIterable.Functions.toList(searchRequestIterable);
      if (searchRequestCollection == null || searchRequestCollection.size() == 0) {
      	log.info("Not Found filter");
      	return;
      }
      
      
      /* 全てのフィルターをループ処理 */
      long searchResultCount = 0;
      long excludeCount = 0;
      long successCount = 0;
      long errorCount = 0;
      
      /* 正規表現文字をエスケープ */
      if (isRegexSearch == false) {
      	searchString = java.util.regex.Pattern.quote(searchString);
      }
      java.util.regex.Pattern searchPattern = java.util.regex.Pattern.compile(searchString);
      
      for (com.atlassian.jira.issue.search.SearchRequest searchRequest : searchRequestCollection) {
      
          /* フィルター名 */
      	String filterNameString = searchRequest.getName();
        
      	/* 探索対象の文字列が見つからなかった場合次へ */
          if (searchPattern.matcher(filterNameString).find() == false) {
      		continue;
          }
      
      	searchResultCount++;
      	
      	/* 置換から除外したいフィルターIDの場合、スキップした旨をログ出力 */
      	if (excludeList.contains(searchRequest.getId())) {
      		log.error("EXCLUDE filter: ID>"  + searchRequest.getId() + " Name>" + searchRequest.getName());
      		excludeCount++;
      		continue;
      	}
      
      	/* 探索対象の文字列にヒットした場合、置換前のフィルター名をログ出力 */
      	log.error("ORIGINAL filter: ID>"  + searchRequest.getId() + " Name>" + searchRequest.getName());
      
          /* 置換 */
          String updateFilterNameString = searchPattern.matcher(filterNameString).replaceAll(replaceString);
      
      	/* 置換エラーの場合、エラー出力して次へ */
      	if (updateFilterNameString == null) {
      		log.error("ERROR(replaceAll): ID>"  + searchRequest.getId() + " Name>" + searchRequest.getName() + " = !!ERROR!!");
      		errorCount++;
      		continue;
      	}
      
      	successCount++
      
         /* dry runは実際にデータは更新しないで次へ */
      	if (isDryrun == true) {
      		continue;
      	}
      
      	/* データ更新 */
      	searchRequest.setName(updateFilterNameString);
      	searchRequestManager.update(searchRequest);
      	log.error("SUCESS(update): ID>"  + searchRequest.getId() + " Name>" + searchRequest.getName());
      }
      
      log.error(String.format("REPALCE END(dryRun: %s): AllFilter(%d), SearchResult(%d), SUCESS(%d), EXCLUDE(%d), ERROR(%d)", isDryrun, searchRequestCollection.size(), searchResultCount, successCount, excludeCount, errorCount));

      (警告) 上記スクリプトを使用される場合は必ず検証環境などで検証してください。

       

      最後にフィルター名を変更するとJQLとかで  filter = フィルター名 の書式で使用していると、そのフィルターが動作に影響受ける場合があるのでご注意ください。

      参考になりましたら幸いです。

      1. 矢矧

        回答ありがとうございます。

        いただいたScriptRunnerを検証環境で試してみます。

      2. 矢矧

        いただいたスクリプトで検証してみましたが、

        フィルター名変更出来ませんでした。

        ご回答いただいたので、ご連絡まで。

      3. Kengo Ohsaki

        矢矧-san,

        出来ませんでしたか...出来るような回答をしてしまい申し訳ございませんでした。

        もし検証して変更する方法が見つかりましたら

        後学のために回答まで記載いただければ幸いです。

        申し訳ございませんでした。

         

      4. 矢矧

        大崎さん

        ごめんなさい。いただいたスプリクトでできました。

      5. Kengo Ohsaki

        矢矧-san,

        いえいえ、よかったです!

        検証せず、なんとなく書いたスクリプトでしたので結果としてよかったです。

        ご連絡ありがとうございました。

      Commentコメントを追加...
    2.  
      1
      0
      -1

      フィルター内のクエリを一括変更したい場合は、下記スクリプトでできました。

      他環境へデータ移行した際に、CFID等のIDがずれ全部のクエリを手動修正するが大変な時に利用できると考えております。

      ※補足

      ・ScriptRunnerのScriptConsoleで実施可
      ・下記スクリプトはサンプルのため検証環境で期待した動作をするか確認した上で利用して下さい。

      import com.atlassian.jira.component.ComponentAccessor;
      import com.atlassian.jira.issue.search.SearchRequestManager;
      import com.atlassian.jira.user.ApplicationUser;
      import com.atlassian.jira.bc.issue.search.SearchService;
      import com.atlassian.jira.bc.filter.SearchRequestService;
      import com.atlassian.jira.bc.JiraServiceContextImpl;
      import com.atlassian.jira.issue.search.SearchRequest;
      import com.atlassian.query.Query
      import com.atlassian.jira.util.collect.EnclosedIterable;
      
      ApplicationUser adminUser = ComponentAccessor.getUserManager().getUserByName("admin");
      JiraServiceContextImpl queryReplaceUser = new JiraServiceContextImpl(adminUser);
      
      String searchString  = "cf\\[10139\\]";
      String replaceString = "cf\\[10141\\]";
      
      /* 各種マネジャーオブジェクト取得 */
      SearchRequestManager searchRequestManager = ComponentAccessor.getComponent(SearchRequestManager.class);
      SearchService searchService = ComponentAccessor.getComponent(SearchService.class);
      SearchRequestService searchRequestService = ComponentAccessor.getComponent(SearchRequestService)
      
      /* JIRAに登録されている全てのフィルターを取得 */
      final EnclosedIterable<SearchRequest> searchRequestIterable = searchRequestManager.getAll();
      if (searchRequestIterable == null) {
          log.error("ERROR(searchRequestManager.getAll): !!NULL ERROR!!");
          return;
      }
      final java.util.Collection<com.atlassian.jira.issue.search.SearchRequest> searchRequestCollection = EnclosedIterable.Functions.toList(searchRequestIterable);
      if (searchRequestCollection == null || searchRequestCollection.size() == 0) {
          log.info("Not Found filter");
          return;
      }
      
      java.util.regex.Pattern searchPattern = java.util.regex.Pattern.compile(searchString);
      for (com.atlassian.jira.issue.search.SearchRequest searchRequest : searchRequestCollection) {
      
          String fillterQueryString = searchRequest.getQuery().getQueryString();
          if (searchPattern.matcher(fillterQueryString).find() == false) {
              continue;
          }
          
          log.warn(searchRequest.getName());
          log.warn(searchRequest.getQuery().getQueryString());
          log.warn("\r\n");
          
          String newQueryString = searchPattern.matcher(searchRequest.getQuery().getQueryString()).replaceAll(replaceString);
          Query newQuery = searchService.parseQuery(adminUser, newQueryString).query;
          searchRequest.setQuery(newQuery);
          searchRequestService.updateFilter(queryReplaceUser, searchRequest);
          
      }
      
      
      
        Commentコメントを追加...