Jira Cloud Migration Assistant (JCMA) ですべてのボードとフィルターを移行する方法

お困りですか?

アトラシアン コミュニティをご利用ください。

コミュニティに質問

プラットフォームについて: Server および Data Center のみ。この記事は、Server および Data Center プラットフォームのアトラシアン製品にのみ適用されます。

Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.

*Fisheye および Crucible は除く

 

Jira Cloud Migration Assistant 1.10.0 以降を使用して、プロジェクト間のボードとフィルターをクラウドに移行できるようになりました。

このお知らせの詳細

プロジェクト間のボードとフィルターの移行に関する詳細

目的

このドキュメントでは、プロジェクト横断ボードを Jira Cloud Migration Assistant (JCMA) 経由で移行するための最新の機能フラグの利用方法をご説明します。

重要: 機能フラグは実験段階であることを、サポート、CMM、カスタマーが認識しておく必要があります。機能フラグによって移行に支障が生じた場合、アトラシアンは可能な限りのサポートを提供しますが、修正やインシデント対応は保証されません。機能フラグはすべてのエッジ ケースを網羅していません。機能フラグの利用が唯一の選択肢である場合は、機能フラグを有効にして、移行の完全なテストを行ってください。機能フラグで問題が発生した場合は、手動での回避策をご検討ください。

手順

このガイドでは、次のような特定の機能を取り上げます。

  • プロジェクト横断ボードとフィルター

  • 移行するプロジェクトに直接関連しないボード

  • 非アクティブなユーザーや削除されたユーザーに紐づくボード/フィルター

  • 移行されないボードが使用しているフィルター (個人用フィルターを含む)

ここでは、確認すべき重要な手順が 2 つあります。

機能フラグが有効である場合、JCMA にはプロジェクト横断ボードまたはすべてのフィルターの移行の進捗が表示されません。代わりに次のように表示される場合があります。

  • 移行の詳細に含まれるすべての項目に緑色のチェックマークがついている

  • 移行ステークホルダーが Migration running または Migration incomplete (インポート側のエラーが発生した場合、または最後の CROSS_PROJECT_DATA 手順)

環境

  • Jira 7.6 以降

  • Jira Cloud Migration Assistantバージョン 1.7.8 以降

サニティー チェック

JCMA で移行計画を実行する管理者ユーザーは、移行されるすべてのプロジェクトに対する「プロジェクトの参照」権限を持っている必要があります。詳細は MIG-1089 バグをご参照ください。

すべてのボードとフィルターを移行する前に、Jira Server のデータベースでいくつかの健全性チェック (と軽微な修正) を実行する必要があります。

JCMA は、フィルターが単一のプロジェクトを参照する場合にのみ、プロジェクトを含むボードを検索します。プロジェクト横断ボードやフィルターを移行する際、JCMA がボードの場所をボード管理者 (所有者) に設定します。ボード管理者またはフィルター所有者が非アクティブである場合は、JCMA によってプロジェクトの場所が適切に割り当てられない可能性があります。ボードやフィルターを正常に移行するために、こうした詳細を確認することをお勧めします。

すべてのボードとフィルターを移行する前に、次の事項をチェックしましょう。

  1. ボードは有効なフィルターに関連付けられている必要があります

  2. ボードの列は有効なステータスに関連付けられている必要があります

  3. クイック フィルターの無効な JQL が修正されている必要があります

  4. メール アドレスなどの個人データが、いずれのフィルターからも削除されている必要があります

  5. 共有権限の設定が有効なグループを参照している必要があります

  6. 非アクティブなユーザーや削除されたユーザーによって所有/作成されたボードやフィルターが、有効な所有者に割り当てられている必要があります

移行前チェック

次のような変更においては、データベース管理者または SQL クエリの利用方法を知っているユーザーが必要となります。

データベース レベルでのデータの変更が含まれるため、変更を行う際には十分にご注意ください。

データベースを変更する前に、データのバックアップを必ず行いましょう。可能な場合は、まずステージング サーバーで SQL コマンドの変更、挿入、更新、または削除のテストを行うことをご検討ください。

移行の成功率を最大限に高めるためにも、ボードとフィルターの移行を試みる前に、サーバー インスタンスで次に示す項目をチェックすることをお勧めします。

存在しないフィルターにリンクされているボード

Jira 管理者が DB からオブジェクトを削除した場合や、Jira のバージョンが古い場合は、データの整合性が失われる可能性があります。また、存在しないフィルターにボードがリンクするような不一致につながる可能性もあります。

さらに、移行を実行する Jira 管理者が UI 経由で対象のフィルターやボードを見つけて修正するための権限 (DB レベルで権限を変更して Jira を再起動した場合を除く) を持っていない可能性があります。

機能しない (壊れた) ボードを修復するには、次のようないくつかの方法があります。

検出

PostgreSQL

SELECT DISTINCT 
       rv."ID"              AS "Board ID"
     , rv."NAME"            AS "Board Name"
     , rv."OWNER_USER_NAME" AS "Board Owner"
     , ba."RAPID_VIEW_ID"   AS "Foreign Key ID from the Board Admins table"
  FROM "AO_60DB71_RAPIDVIEW" rv
  LEFT JOIN searchrequest sr ON (rv."SAVED_FILTER_ID" = sr.id)
  LEFT JOIN "AO_60DB71_BOARDADMINS" ba ON (rv."ID" = ba."RAPID_VIEW_ID")
 WHERE NOT EXISTS ( SELECT *
                      FROM searchrequest
                      WHERE id = rv."SAVED_FILTER_ID" )
 ORDER BY rv."ID";

Oracle、MySQL、MSSQL

SELECT DISTINCT 
       rv.ID              AS "Board ID"
     , rv.NAME            AS "Board Name"
     , rv.OWNER_USER_NAME AS "Board Owner"
     , ba.RAPID_VIEW_ID   AS "Foreign Key ID from the Board Admins table"
  FROM AO_60DB71_RAPIDVIEW rv
  LEFT JOIN searchrequest sr ON (rv.SAVED_FILTER_ID = sr.id)
  LEFT JOIN AO_60DB71_BOARDADMINS ba ON (rv.ID = ba.RAPID_VIEW_ID)
 WHERE NOT EXISTS ( SELECT *
                      FROM searchrequest
                      WHERE id = rv.SAVED_FILTER_ID )
 ORDER BY rv.ID;
修復: 壊れたボード用のダミー フィルターを作成する

Jira の UI でフィルターを作成します。次の SQL SELECT を実行してフィルター ID を取得し、それを使って壊れたボードにそれぞれリンクします。

フィルター ID を取得すると、次の UPDATE 文によって、壊れたボードが新しいフィルターに再び関連付けされます。

すべてのデータベース

SELECT id FROM searchrequest WHERE filtername = '<dummy filter name>';

PostgreSQL

UPDATE "AO_60DB71_RAPIDVIEW" rv
   SET "SAVED_FILTER_ID" = <filter ID from the SELECT above>
 WHERE NOT EXISTS ( SELECT id FROM searchrequest WHERE id = rv."SAVED_FILTER_ID" );

ORACLE、MYSQL、MSSQL サーバー

UPDATE AO_60DB71_RAPIDVIEW
   SET SAVED_FILTER_ID = <filter ID from the SELECT above>
 WHERE NOT EXISTS ( SELECT id FROM searchrequest WHERE id = AO_60DB71_RAPIDVIEW.SAVED_FILTER_ID );
修正: REST を使用した無効なフィルターを含むボードを削除する

ボードを削除する安全な方法は、REST API を使用することです。

REST API の使用方法に関するガイダンスは、Jira REST API の例を参照してください。

ボードの削除方法の定義とパラメータについては、「ボードの削除」を参照してください。

  • ボード ID は、影響を受けるボードを特定するためのクエリと同じボード ID です。

curl を使用してボードを削除する REST 呼び出しの例

curl
curl -u username:password -X DELETE -H "Content-Type: application/json" https://jiraserver.com/rest/agile/1.0/board/{board ID}

ボードを閲覧する権限がない場合は、エラーが表示されることがあります。

自分をボードの所有者に変更するには、以下の SQL クエリを実行します。

PostgreSQL の例

UPDATE "AO_60DB71_RAPIDVIEW" 
SET "OWNER_USER_NAME" = '{my username}'
WHERE "ID" = {board ID}; 

ユーザー名がわからない場合は、CWD_USER テーブルを確認してください。

PostgreSQL の例

SELECT user_name 
FROM cwd_user 
WHERE email_address = 'myuser@example.com';

自分を所有者に変更したら、REST 呼び出しをもう一度試すことができます。

修正: フィルターが無効なボードをデータベースから削除する

「AO_60DB71_BOARDADMINS」テーブルにボード ID が存在する場合、まずはテーブルから ID を削除する必要があります。これを行わないと、「AO_60DB71_RAPIDVIEW」テーブルからボードを削除する際に外部キー制約エラーが発生します (上の画像をご参照ください)。

壊れたボードを検出する上記のクエリでは、「AO_60DB71_BOARDADMINS」テーブルからデータを取得して、必要に応じてそこから削除する必要のある ID を提供します。

注意: この方法では、さまざまなデータベース制約エラーが発生することが知られています。発生した場合は、別の方法を試すことをお勧めします。 

AO_60DB71_BOARDADMINS テーブルからボードを削除するには、次の手順に従います (必要な場合)。

PostgreSQL

DELETE
  FROM "AO_60DB71_BOARDADMINS"
WHERE "RAPID_VIEW_ID" IN (<ID of a Board>, <ID of another Board>, ...);

ORACLE、MYSQL、MSSQL サーバー

DELETE
  FROM AO_60DB71_BOARDADMINS
WHERE RAPID_VIEW_ID IN (<ID of a Board>, <ID of another Board>, ...);

AO_60DB71_RAPIDVIEW テーブルからボードを削除するには、次の手順に従います。

PostgreSQL

DELETE
  FROM "AO_60DB71_RAPIDVIEW" USING "AO_60DB71_RAPIDVIEW" rv
  LEFT JOIN searchrequest sr ON (rv."SAVED_FILTER_ID" = sr.id)
 WHERE "AO_60DB71_RAPIDVIEW"."ID" = rv."ID"
   AND NOT EXISTS ( SELECT *
                      FROM searchrequest
                     WHERE id = rv."SAVED_FILTER_ID" );

ORACLE

DELETE 
  FROM AO_60DB71_RAPIDVIEW rv
WHERE EXISTS ( SELECT rv.ID
                 FROM AO_60DB71_RAPIDVIEW rv
                 LEFT JOIN searchrequest sr ON (rv.SAVED_FILTER_ID = sr.id)
                WHERE NOT EXISTS ( SELECT *
                                     FROM searchrequest
                                    WHERE id = rv.SAVED_FILTER_ID ))

MYSQL、MSSQL サーバー

DELETE rv
  FROM AO_60DB71_RAPIDVIEW rv
  LEFT JOIN searchrequest sr ON (rv.SAVED_FILTER_ID = sr.id)
 WHERE NOT EXISTS ( SELECT *
                      FROM searchrequest
                      WHERE id = rv.SAVED_FILTER_ID );


存在しないステータスにリンクされている列をフィルタリングする (オプション)

JCMA の最新バージョンでは、ステータスが欠落しているフィルターを移行できます。これによって、フィルターに依存しているボードが壊れた状態になる可能性があります。そのような箇所をすべて見つけて修正したい場合は、次の方法を実行します。

検出

存在しないステータス ID が含まれるボード列のステータスをすべて検索します。

PostgreSQL

SELECT rv."ID"   AS "Board ID"
     , rv."NAME" AS "Board Name"
     , c."NAME"  AS "Column Name"
     , i.pname   AS "Issue Status Name"
FROM "AO_60DB71_RAPIDVIEW" rv
JOIN "AO_60DB71_COLUMN" c ON (rv."ID" = c."RAPID_VIEW_ID")
JOIN "AO_60DB71_COLUMNSTATUS" cs ON (c."ID" = cs."COLUMN_ID")
LEFT JOIN issuestatus i ON (i.id = cs."STATUS_ID")
WHERE NOT EXISTS ( SELECT id 
                     FROM issuestatus 
                    WHERE id = cs."STATUS_ID" );

ORACLE、MYSQL、MSSQL サーバー

SELECT rv.ID   AS "Board ID"
     , rv.NAME AS "Board Name"
     , c.NAME  AS "Column Name"
     , i.pname AS "Issue Status Name"
FROM AO_60DB71_RAPIDVIEW rv
JOIN AO_60DB71_COLUMN c ON (rv.ID = c.RAPID_VIEW_ID)
JOIN AO_60DB71_COLUMNSTATUS cs ON (c.ID = cs.COLUMN_ID)
LEFT JOIN issuestatus i ON (i.id = cs.STATUS_ID)
WHERE NOT EXISTS ( SELECT id 
                     FROM issuestatus 
                    WHERE id = cs.STATUS_ID );
UI を使用する
Jira UI でボード (上記の SQL SELECT クエリの出力に記載されたもの) を開いて、ステータスを削除します。
DB クエリ

PostgreSQL

DELETE
  FROM "AO_60DB71_COLUMNSTATUS" col
 WHERE NOT EXISTS ( SELECT * FROM issuestatus WHERE id = col."STATUS_ID" );
DELETE
  FROM "AO_60DB71_COLUMN" col
 WHERE NOT EXISTS ( SELECT * FROM "AO_60DB71_COLUMNSTATUS" WHERE "COLUMN_ID" = col."ID" );

ORACLE

DELETE
  FROM AO_60DB71_COLUMNSTATUS col
 WHERE NOT EXISTS ( SELECT * FROM issuestatus WHERE id = col.STATUS_ID );
DELETE
  FROM AO_60DB71_COLUMN col
 WHERE NOT EXISTS ( SELECT * FROM AO_60DB71_COLUMNSTATUS WHERE COLUMN_ID = col.ID );

MYSQL、MSSQL サーバー

DELETE col
  FROM AO_60DB71_COLUMNSTATUS col
 WHERE NOT EXISTS ( SELECT * FROM issuestatus WHERE id = col.STATUS_ID );
DELETE col
  FROM AO_60DB71_COLUMN col
 WHERE NOT EXISTS ( SELECT * FROM AO_60DB71_COLUMNSTATUS WHERE COLUMN_ID = col.ID );

クイック フィルター内の無効な JQL

フィルターに特殊文字が含まれていると、次のエラーによって移行プロセスが失敗する可能性があります。

project-import We couldn't import Board <Board ID> (プロジェクトインポート ボード <ボード ID> をインポートできませんでした)。理由: クイック フィルターの JQL が無効です: 無効な JQL : JQL クエリのエラー: 「@」文字は予約済みの JQL 文字です。文字列内で囲むか、代わりにエスケープ文字「\u0040」を使用する必要があります。(行 1、文字 34)

メール アドレスについては、次のセクションもご参照ください。

検出

PostgreSQL

SELECT rv."NAME" AS "Board Name"
     , qf."NAME" AS "Quick Filter Name"
 FROM "AO_60DB71_RAPIDVIEW" rv
INNER JOIN "AO_60DB71_QUICKFILTER" qf ON (rv."ID" = qf."RAPID_VIEW_ID")
 WHERE qf."LONG_QUERY" LIKE '%@%';

ORACLE、MYSQL、MSSQL サーバー

SELECT rv.NAME AS "Board Name"
     , qf.NAME AS "Quick Filter Name"
 FROM AO_60DB71_RAPIDVIEW rv
INNER JOIN AO_60DB71_QUICKFILTER qf ON (rv.ID = qf.RAPID_VIEW_ID)
 WHERE qf.LONG_QUERY LIKE '%@%';

UI によってフィルターの JQL を更新して、サポートされていない文字を削除します。

フィルターに含まれるメール アドレスなどの個人情報

この事前チェックは、次のような問題を防ぐために実行します。

Error in the JQL Query: The character '@' is a reserved JQL character. You must enclose it in a string or use the escape '\u0040' instead. (line 1, character 52)

「@」は予約文字ですが、サーバー/DC で「@」記号を含むフィルターのメール アドレスが二重引用符で囲まれていれば移行が可能となり、フィルターが Cloud サイトで機能するようになります。アカウント ID などに変更する必要はありません。

次の SQL クエリを実行すると、個人データ(メール アドレス)を含むすべてのフィルターを検索して、正しい書式であるかどうかを確認できます。次に例を示します。

project = "ABC" AND reporter = "username@yourcompany.com"
検出
SELECT * FROM searchrequest WHERE reqcontent LIKE '%@%';


共有権限に無効なグループがある (オプション)

フィルターの共有権限の設定でグループが参照されているものの、そのグループ自体がすでに Jira に存在しないというケースがあります。フィルターは移行されますが、そのフィルターが破損するか、アクセスできなくなる可能性があります。壊れたボードを移行するリスクを軽減したい場合は、移行前にご確認ください。ユーザー & グループのスコープで移行する場合は、参照先のグループが現在のプランに含まれていないと、フィルターが破損する可能性があります。

これは、グループへの参照を含むフィルターの JQL には適用されません。
検出
SELECT sr.filtername AS filter_name , sp.entitytype AS bla , sp.param1 AS group_name FROM searchrequest sr JOIN sharepermissions sp ON (sr.id = sp.entityid) WHERE sp.entitytype = 'SearchRequest' AND sp.sharetype = 'group' AND NOT EXISTS ( SELECT id FROM cwd_group g WHERE g.group_name = sp.param1 )
修復のオプション
  1. Jira Server でグループを再作成します。

  2. 共有権限エントリを削除します。

    1. UI でフィルター/ボード/プロジェクトを編集して、権限設定で無効なグループへの参照を削除します。

  3. 共有権限のグループを置き換えます。

    1. 上記と同じですが、参照を削除する代わりに、有効なグループに置き換えます。

非アクティブなユーザーや削除されたユーザーが所有するボード/フィルター

移行されたフィルターの所有権が、クラウド上で非アクティブであるユーザーを参照している場合があります。関連するプロジェクト横断ボードの場所は、移行後のプロセスで修正する必要があります。ただし、移行前に所有者を修正するほうが、より実現可能な作業です。 

非アクティブなユーザーが所有するボード

検出
PostgreSQL
SELECT rv."NAME"               AS "Board name"
     , cwu.lower_user_name     AS "Board inactive owner username"
     , cwu.lower_email_address AS "Board inactive owner email address"    
     , cwu.display_name        AS "Board inactive owner display name"
     , au.user_key             AS "Board inactive owner user key"
  FROM cwd_user cwu
 INNER JOIN app_user au         ON (cwu.lower_user_name = au.lower_user_name)
  JOIN "AO_60DB71_RAPIDVIEW" rv ON (rv."OWNER_USER_NAME" = cwu.lower_user_name OR rv."OWNER_USER_NAME" = au.user_key)
 WHERE cwu.active = 0
 ORDER BY rv."ID";


Oracle、MySQL、MSSQL


Oracle、MySQL、MSSQL
SELECT rv.NAME                 AS "Board name"
     , cwu.lower_user_name     AS "Board inactive owner username"
     , cwu.lower_email_address AS "Board inactive owner email address"    
     , cwu.display_name        AS "Board inactive owner display name"
     , au.user_key             AS "Board inactive owner user key"
  FROM cwd_user cwu
 INNER JOIN app_user au       ON (cwu.lower_user_name = au.lower_user_name)
  JOIN AO_60DB71_RAPIDVIEW rv ON (rv.OWNER_USER_NAME = cwu.lower_user_name OR rv.OWNER_USER_NAME = au.user_key)
 WHERE cwu.active = 0
 ORDER BY rv.ID;


修正 1 - Jira UI (ボード設定) でボード (上記の SQL SELECT クエリの出力に記載されたもの) を開き、手動でその所有者を変更します。これが行えない場合は以降の DB 修正のアプローチに進みます。
修正 2 - データベースから直接ボードを更新して所有者をアクティブ ユーザーに変更

問題のあるボードのボード所有者として、非アクティブなユーザーの代わりにアクティブな Jira ユーザーを選択するようにしてください。

MySQL ERROR 1175 が返される場合は、「MySQL Workbench で UPDATE 中に MySQL エラー コード 1175 が発生する」をご確認ください。

PostgresSQL
UPDATE "AO_60DB71_RAPIDVIEW"
   SET "OWNER_USER_NAME" = '<user name that will be the new owner of these boards>'
 WHERE "ID" IN ( SELECT rv."ID"
                   FROM cwd_user cwu
                  INNER JOIN app_user au ON (cwu.lower_user_name = au.lower_user_name)
                   JOIN "AO_60DB71_RAPIDVIEW" rv ON (rv."OWNER_USER_NAME" = cwu.lower_user_name OR rv."OWNER_USER_NAME" = au.user_key)
                  WHERE cwu.active = 0 );
Oracle、MSSQL Server
UPDATE AO_60DB71_RAPIDVIEW
   SET OWNER_USER_NAME = '<user name that will be the new owner of these boards>'
 WHERE ID IN ( SELECT rv.ID
                 FROM cwd_user cwu
                INNER JOIN app_user au ON (cwu.lower_user_name = au.lower_user_name)
                 JOIN AO_60DB71_RAPIDVIEW rv ON (rv.OWNER_USER_NAME = cwu.lower_user_name OR rv.OWNER_USER_NAME = au.user_key)
                WHERE cwu.active = 0 );
MySQL
SET SQL_SAFE_UPDATES = 0;
 
UPDATE AO_60DB71_RAPIDVIEW
   SET OWNER_USER_NAME = '<user name that will be the new owner of these boards>'
 WHERE ID IN ( SELECT ID
                 FROM ( SELECT rv.ID
                          FROM cwd_user cwu
                         INNER JOIN app_user au ON (cwu.lower_user_name = au.lower_user_name)
                          JOIN AO_60DB71_RAPIDVIEW rv ON (rv.OWNER_USER_NAME = cwu.lower_user_name OR rv.OWNER_USER_NAME = au.user_key)
                         WHERE cwu.active = 0 ) AS t );
 
SET SQL_SAFE_UPDATES = 1;


非アクティブなユーザーが所有するフィルター

検出
PostgreSQL、MySQL
SELECT DISTINCT sr.filtername  AS "Filter name"
     , sr.username             AS "Filter username"
     , sr.authorname           AS "Filter author"
     , cwu.lower_email_address AS "Filter inactive user email address"
     , cwu.display_name        AS "Filter inactive user display name"
     , au.user_key             AS "Filter inactive user user key"
     , CASE WHEN cwu.active = 0 THEN 'Inactive' ELSE 'Active' END AS "User status"
     , sr.reqcontent           AS "Filter JQL"
  FROM cwd_user cwu
 INNER JOIN app_user au ON (cwu.lower_user_name = au.lower_user_name)
  JOIN searchrequest sr ON ( (sr.username = cwu.lower_user_name OR sr.username = au.user_key) OR (sr.authorname = cwu.lower_user_name OR sr.authorname = au.user_key) )
 WHERE cwu.active = 0 ;
Oracle
SELECT DISTINCT sr.filtername  AS "Filter name"
     , sr.username             AS "Filter username"
     , sr.authorname           AS "Filter author"
     , cwu.lower_email_address AS "Filter inactive user email address"
     , cwu.display_name        AS "Filter inactive user display name"
     , au.user_key             AS "Filter inactive user user key"
     , CASE WHEN cwu.active = 0 THEN 'Inactive' ELSE 'Active' END AS "User status"
     , CAST(sr.reqcontent AS VARCHAR2(3000)) AS "Filter JQL"
  FROM cwd_user cwu
 INNER JOIN app_user au ON (cwu.lower_user_name = au.lower_user_name)
  JOIN searchrequest sr ON ( (sr.username = cwu.lower_user_name OR sr.username = au.user_key) OR (sr.authorname = cwu.lower_user_name OR sr.authorname = au.user_key) )
 WHERE cwu.active = 0 ;
MS SQL
SELECT DISTINCT sr.filtername  AS "Filter name"
     , sr.username             AS "Filter username"
     , sr.authorname           AS "Filter author"
     , cwu.lower_email_address AS "Filter inactive user email address"
     , cwu.display_name        AS "Filter inactive user display name"
     , au.user_key             AS "Filter inactive user user key"
     , CASE WHEN cwu.active = 0 THEN 'Inactive' ELSE 'Active' END AS "User status"
     , CAST(sr.reqcontent AS nvarchar(max)) AS "Filter JQL"
  FROM cwd_user cwu
 INNER JOIN app_user au ON (cwu.lower_user_name = au.lower_user_name)
  JOIN searchrequest sr ON ( (sr.username = cwu.lower_user_name OR sr.username = au.user_key) OR (sr.authorname = cwu.lower_user_name OR sr.authorname = au.user_key) )
 WHERE cwu.active = 0 ;


修正 1 - Jira UI (ボード/フィルター設定) でフィルター (上記の SELECT SQL 文の出力に記載されたもの) を開いて所有者を変更
修正 2 - データベースから直接フィルターを更新して所有者をアクティブ ユーザーに変更

問題のあるフィルターのフィルター所有者として、非アクティブなユーザーの代わりにアクティブな Jira ユーザーを選択するようにしてください。

ユーザーの user_key は、app_user テーブルから取得する必要があります。

SELECT user_key FROM app_user WHERE lower_user_name = '<user name of the new owner of the filters>'

この user_key を以下の UPDATE 文に入力します。

MySQL ERROR 1175 が返される場合は、「MySQL Workbench で UPDATE 中に MySQL エラー コード 1175 が発生する」をご確認ください。

PostgreSQL、Oracle、MSSQL
UPDATE searchrequest
   SET username = '<user_key that will be the new owner of these filters>'
     , authorname = '<user_key that will be the new owner of these filters>'
 WHERE id IN ( SELECT sr.id
                 FROM cwd_user cwu
                INNER JOIN app_user au ON (cwu.lower_user_name = au.lower_user_name)
                 JOIN searchrequest sr ON ( (sr.username = cwu.lower_user_name OR sr.username = au.user_key) OR (sr.authorname = cwu.lower_user_name OR sr.authorname = au.user_key) )
                WHERE cwu.active = 0 );
MySQL
SET SQL_SAFE_UPDATES = 0;
 
UPDATE searchrequest     
   SET username = '<user_key that will be the new owner of these filters>'
     , authorname = '<user_key that will be the new owner of these filters>'
 WHERE id IN ( SELECT id
                 FROM ( SELECT sr.id
                          FROM cwd_user cwu
                         INNER JOIN app_user au ON (cwu.lower_user_name = au.lower_user_name)
                          JOIN searchrequest sr ON ( (sr.username = cwu.lower_user_name OR sr.username = au.user_key) OR (sr.authorname = cwu.lower_user_name OR sr.authorname = au.user_key) )
                         WHERE cwu.active = 0 ) AS t );
 
SET SQL_SAFE_UPDATES = 1;


削除済みのユーザーが所有するボード

検出
PostgreSQL
SELECT rv."NAME"         AS "Board Name"
     , u.lower_user_name AS "Deleted Username"
 FROM "AO_60DB71_RAPIDVIEW" rv
 JOIN app_user u        ON (rv."OWNER_USER_NAME" = u.user_key)
 LEFT JOIN cwd_user cwu ON (u.lower_user_name = cwu.lower_user_name)
WHERE NOT EXISTS ( SELECT *
                     FROM cwd_user
                    WHERE lower_user_name = u.lower_user_name );
Oracle、MySQL、MSSQL
SELECT rv.NAME           AS "Board Name"
     , u.lower_user_name AS "Deleted Username"
 FROM AO_60DB71_RAPIDVIEW rv
 JOIN app_user u        ON (rv.OWNER_USER_NAME = u.user_key)
 LEFT JOIN cwd_user cwu ON (u.lower_user_name = cwu.lower_user_name)
WHERE NOT EXISTS ( SELECT *
                     FROM cwd_user
                    WHERE lower_user_name = u.lower_user_name );


修正 1 - Jira UI (ボード設定) でボード (上記の SELECT SQL 文の出力に記載されたもの) を開いて所有者を変更
修正 2 - データベースから直接ボードを更新して所有者をアクティブ ユーザーに変更

問題のあるボードのボード所有者として、非アクティブなユーザーの代わりにアクティブな Jira ユーザーを選択するようにしてください。

PostgreSQL
UPDATE "AO_60DB71_RAPIDVIEW"
   SET "OWNER_USER_NAME" = '<user name that will be the new owner of these boards>'
 WHERE "ID" IN ( SELECT rv."ID"
                   FROM "AO_60DB71_RAPIDVIEW" rv
                   JOIN app_user u        ON (rv."OWNER_USER_NAME" = u.user_key)
                   LEFT JOIN cwd_user cwu ON (u.lower_user_name = cwu.lower_user_name)
                  WHERE NOT EXISTS ( SELECT *
                                       FROM cwd_user
                                      WHERE lower_user_name = u.lower_user_name ));
Oracle、MSSQL
UPDATE AO_60DB71_RAPIDVIEW
   SET OWNER_USER_NAME = '<user name that will be the new owner of these boards>'
 WHERE ID IN ( SELECT rv.ID
                 FROM AO_60DB71_RAPIDVIEW rv
                 JOIN app_user u        ON (rv.OWNER_USER_NAME = u.user_key)
                 LEFT JOIN cwd_user cwu ON (u.lower_user_name = cwu.lower_user_name)
                WHERE NOT EXISTS ( SELECT *
                                     FROM cwd_user
                                    WHERE lower_user_name = u.lower_user_name ));
MySQL
UPDATE AO_60DB71_RAPIDVIEW rv
  JOIN app_user u        ON (rv.OWNER_USER_NAME = u.user_key)
  LEFT JOIN cwd_user cwu ON (u.lower_user_name = cwu.lower_user_name)
   SET OWNER_USER_NAME = '<user name that will be the new owner of these boards>'
 WHERE NOT EXISTS ( SELECT *
                      FROM cwd_user
                     WHERE lower_user_name = u.lower_user_name );


削除済みのユーザーが所有するフィルター

検出
PostgreSQL、Oracle、MySQL、MSSQL
SELECT sr.filtername     AS "Filter name"
     , u.lower_user_name AS "Username"
  FROM searchrequest sr
  JOIN app_user u        ON (sr.authorname = u.lower_user_name)
  LEFT JOIN cwd_user cwu ON (u.lower_user_name = cwu.lower_user_name)
 WHERE NOT EXISTS ( SELECT *
                      FROM cwd_user
                     WHERE lower_user_name = u.lower_user_name );


修正 1 - Jira UI (ボード/フィルター設定) でフィルター (上記の SELECT SQL 文の出力に記載されたもの) を開いて所有者を変更
修正 2 - データベースから直接フィルターを更新して所有者をアクティブ ユーザーに変更

問題のあるフィルターのフィルター所有者として、非アクティブなユーザーの代わりにアクティブな Jira ユーザーを選択するようにしてください。

ユーザーの user_key は、app_user テーブルから取得する必要があります。

SELECT user_key FROM app_user WHERE lower_user_name = '<user name of the new owner of the filters>'

この user_key を以下の UPDATE 文に入力します。

MySQL ERROR 1175 が返される場合は、「MySQL Workbench で UPDATE 中に MySQL エラー コード 1175 が発生する」をご確認ください。

PostgreSQL、Oracle、MSSQL
UPDATE searchrequest
   SET username = '<user_key that will be the new owner of these filters>'
     , authorname = '<user_key that will be the new owner of these filters>'
 WHERE id IN ( SELECT sr.id
                 FROM searchrequest sr
                 JOIN app_user u        ON (sr.authorname = u.lower_user_name)
                 LEFT JOIN cwd_user cwu ON (u.lower_user_name = cwu.lower_user_name)
                WHERE NOT EXISTS ( SELECT *
                                     FROM cwd_user
                                    WHERE lower_user_name = u.lower_user_name ));
MySQL
UPDATE searchrequest sr
  JOIN app_user u        ON (sr.authorname = u.lower_user_name)
  LEFT JOIN cwd_user cwu ON (u.lower_user_name = cwu.lower_user_name)
   SET username = '<user_key that will be the new owner of these filters>'
     , authorname = '<user_key that will be the new owner of these filters>'
 WHERE NOT EXISTS ( SELECT *
                      FROM cwd_user
                     WHERE lower_user_name = u.lower_user_name );


マルチプロジェクト ボードの有無を判断する

マルチプロジェクト ボード (と単一プロジェクト ボード) がいくつ存在するのかを確認するには、次の手順に従います。

複数のプロジェクトにわたる JQL を検出する

すべてのデータベース

SELECT * FROM SEARCHREQUEST WHERE REQCONTENT LIKE '%project in%' OR REQCONTENT LIKE '%project%project%'
複数のプロジェクトにわたる権限を検出する

PostgreSQL

SELECT rv."ID"   AS board_id
     , rv."NAME" AS board_name
     , CASE WHEN COUNT(*) > 1 THEN 'Multi-project Board' ELSE 'Single-project Board' END AS board_type
     , COUNT(*)  AS project_count_on_filter
  FROM "AO_60DB71_RAPIDVIEW" rv 
 INNER JOIN searchrequest sr    ON (sr.id = rv."SAVED_FILTER_ID") 
 INNER JOIN sharepermissions sp ON (sp.entityid = sr.id) 
 INNER JOIN project p           ON (p.id = sp.param1::int) 
 WHERE sp.sharetype = 'project' 
 GROUP BY rv."ID", rv."NAME" 
 ORDER BY COUNT(*) DESC;

MySQL

SELECT rv.ID     AS board_id
     , rv.NAME   AS board_name
     , CASE WHEN COUNT(*) > 1 THEN 'Multi-project Board' ELSE 'Single-project Board' END AS board_type
     , COUNT(*)  AS project_count_on_filter
  FROM AO_60DB71_RAPIDVIEW rv 
 INNER JOIN searchrequest sr    ON (sr.id = rv.SAVED_FILTER_ID)
 INNER JOIN sharepermissions sp ON (sp.entityid = sr.id) 
 INNER JOIN project p           ON (p.id = CAST(sp.param1 AS UNSIGNED)) 
 WHERE sp.sharetype = 'project' 
 GROUP BY rv.ID, rv.NAME
 ORDER BY COUNT(*) DESC;

MSSQL サーバー

SELECT rv.ID     AS board_id
     , rv.NAME   AS board_name
     , CASE WHEN COUNT(*) > 1 THEN 'Multi-project Board' ELSE 'Single-project Board' END AS board_type
     , COUNT(*)  AS project_count_on_filter
  FROM AO_60DB71_RAPIDVIEW rv 
 INNER JOIN searchrequest sr    ON (sr.id = rv.SAVED_FILTER_ID)
 INNER JOIN sharepermissions sp ON (sp.entityid = sr.id) 
 INNER JOIN project p           ON (p.id = CAST(sp.param1 AS NUMERIC)) 
 WHERE sp.sharetype = 'project' 
 GROUP BY rv.ID, rv.NAME
 ORDER BY COUNT(*) DESC;

ORACLE

SELECT rv.ID     AS board_id
     , rv.NAME   AS board_name
     , CASE WHEN COUNT(*) > 1 THEN 'Multi-project Board' ELSE 'Single-project Board' END AS board_type
     , COUNT(*)  AS project_count_on_filter
  FROM AO_60DB71_RAPIDVIEW rv 
 INNER JOIN searchrequest sr    ON (sr.id = rv.SAVED_FILTER_ID)
 INNER JOIN sharepermissions sp ON (sp.entityid = sr.id) 
 INNER JOIN project p           ON (p.id = CAST(sp.param1 AS NUMBER)) 
 WHERE sp.sharetype = 'project' 
 GROUP BY rv.ID, rv.NAME
 ORDER BY COUNT(*) DESC;

機能フラグでプロジェクト横断ボードとすべてのフィルターを移行する

初期設定では、JCMA はプロジェクト横断ボードまたはすべてのフィルターを移行しません。この機能は、機能フラグ (ダーク機能とも呼ばれる) の背後に実装されており、有効化する必要があります。機能フラグの使用方法に関する詳細な手順は、「Jira のダーク機能を有効化する」もご参照ください。同様に、移行計画のスコープ外である非公開フィルターも含まれません。

すべてのチェックと変更 (上記のセクションを参照) が完了したら、Jira Server インスタンスで次の機能フラグを追加します。

com.atlassian.jira.migration.export.all.filters
com.atlassian.jira.migration.export.multiprojects.boards

これらのフラグを組み合わせて使用すると、次のものが移行されます

  • 含まれているプロジェクトと関連がないものも含めた、すべてのフィルター (これには個人用フィルターと、現在の計画に含まれていない他のプロジェクトを参照するフィルターも含まれます)

  • 計画内のプロジェクトに関連するすべてのボードと、計画外のプロジェクトを参照するボード (プロジェクト横断ボード)

これらの機能フラグを適用するには、ご利用の Jira Server インスタンスで次の手順に従います。

  • 次の URL に移動します。

    ${Jira_URL}/secure/admin/jira/views/SiteDarkFeatures!default.jspa
  • 上のフラグのテキストを入力します。

  • [追加] をクリックします (Jira の再起動は不要です)。

バージョンの非互換性を回避して、移行時間を最小限に抑えるには、1 つの JCMA 計画のみで 2 つのダーク機能を使用する必要があります (下記の推奨アプローチを参照)。

可能である場合は、JCMA によって単一プロジェクトのボードがすべて移行され、プロジェクトの場所にリンクされます。さらに、まだ移行されていないプロジェクトにボードが依存している場合でも、(複数のプロジェクトを参照するフィルターを含む) プロジェクト横断ボードをボード所有者の場所にキープします。

これらのダーク機能を複数の計画に含めると、含まれているすべてのボードとフィルターが再移行されます。これによって、計画の実行中にサーバー側またはクラウド側でボードやフィルターに変更があった場合は、重複が起こる可能性があります。これはコンフィグ ドリフトと呼ばれます (下記を参照)。

つまり、次のいずれかのやり方を選択するのが推奨の手順となります。

  1. 両方のダーク機能を有効にします。

  2. 完全な JCMA 移行計画 (すべてのプロジェクト) を実行します。

  3. 計画が終了したら、両方のダーク機能を無効にします。

または

  1. いずれのダーク機能も有効化しません

  2. JCMA でプロジェクトを移行します (お客様にとっての最適なシナリオに応じて、1 つまたは複数の計画)。

  3. すべてのプロジェクトを移行したら、両方のダーク機能を有効にします。

  4. 課題 1 つだけを持つダミー プロジェクトを Jira Server に作成します。

  5. JCMA 移行計画を、ダミー プロジェクトのみで実行します。

  6. 計画が終了したら、両方のダーク機能を無効にします。

既知の問題

MIG-1648 - Getting issue details... STATUS

コンフィグ ドリフト

機能が何度か移行されると、コンフィグ ドリフトが起こる可能性があります。コンフィグ ドリフトは通常、移行のフェーズ間、または JCMA で移行計画が実行されている間にサーバー側の設定が変更されると発生します。また、クラウド側に更新があった場合にも発生する可能性があります。

フィルターとボードでは、次のようなケースでコンフィグ ドリフトが発生する可能性があります。

  • 複数の計画 (または移行フェーズ) の期間中に両方の機能フラグ (上記) を設定した場合

  • 計画を実行中 (機能フラグの有無にかかわらず)、あるプロジェクトに関連するフィルターまたはボードを別のプロジェクトに関連するものに変更した場合

後者が起こることは滅多にありませんが、機能フラグを有効にしたまま、ボードまたはフィルターを複数回移行するのはリスクがあることを理解しましょう。

計画間での変更

結果

特別な操作

サーバーでフィルター (JQL) を変更

クラウドでの変更はありません

再移行する前に、クラウドのフィルター (とボード) を削除する

クラウドでフィルター (JQL) を変更

クラウドでの変更はありません


サーバーでボード (設定) を変更

クラウドでボードの設定を更新


クラウドでボード (設定) を変更

クラウドでのボード設定の変更が失われました

クラウドで変更を再実装する

最終更新日 2024 年 4 月 24 日

この内容はお役に立ちましたか?

はい
いいえ
この記事についてのフィードバックを送信する
Powered by Confluence and Scroll Viewport.