18
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Salesforce レコードデータの自動マイグレーションを行う sfdx-migration-automatic

Last updated at Posted at 2019-03-26

Salesforceにおける開発時のデータマイグレーションについて

Salesforceの開発においてScratch組織の利用は安定的かつ継続的な開発サイクルを実現するのに大変有効です。
Salesforce CLIを利用することで、開発コードおよびメタデータのプロビジョニングの自動化はかなり簡単になっています。

しかしながら(特にE2EテストやPullRequestの受入確認においては)必要なデータをあらかじめScratch組織に用意しておくことが求められます。

従来の(使い捨てでない)開発組織を利用する限りにおいては、初回セットアップ時にデータローダーなどでデータ移入を手作業で行ったり、Full/Partial Sandboxを利用したり、またSalesforceのパートナーであればTrialforceの仕組みを利用することもできましたが、使い捨てのScratch組織が前提となったことでこれらはあまり意味がなくなりました。つまり、開発時のデータのマイグレーションを自動化することが求められています。

いままでのデータマイグレーション手法

Salesforceでもある程度大きな開発プロジェクトになってくると、データローダーをコマンドラインで利用してデータ移入を自動化させているプロジェクトもあります。しかしながら、そもそもデータローダーのインターフェースはあまりコマンドラインでの利用を想定したものとは言い難く、さらに後述の依存関係の解決はプロジェクト依存で行わねばならないところがほとんどなのも辛いところです。

テストデータに限定した場合、プロジェクトによってはApexクラスなどで作成および移入を行っているケースもままありますが、コードベースでのデータ生成はメンテナンス性に乏しく、かつ汎用性に欠けるものとなりがちです。さらにガバナなどの制限を考えるとなかなか選択が難しいというのが実際のところではないかと思います。

sfdx の data:tree コマンド

さて、実は Salesforce CLI の標準コマンドに force:data:tree:exportおよびforce:data:tree:import というものがありますが、このコマンドはデータのマイグレーションに利用できます。しかしながら、一度に移入可能なのはSOQLクエリで取得できる範囲に限られるため、複雑なリレーションシップを持ったデータ構造については難しい(3段階以上の関連を持つオブジェクトなど)という弱点がありました。これは内部で移入のためのAPIとしてSObject Tree APIを利用しているためなのですが、なかなか使い所が難しいと感じます。

温故知新: 「開発用デモデータ集」パッケージ

ここで、Salesforceのデモデータのセットをそのまま組織にロードできるような機構というものはいままでなかったのか、少し疑問に思っている方もいるかも知れません。もしかしたら使ったことがある方もいるかも知れませんが、「開発用デモデータ集」というAppExchangeパッケージが古に(2007年〜)存在していました(現在は非公開ですがまだページはある)。

このパッケージはなんとSコントロール(ご存知でしょうか?)の上でAjax Toolkitを利用してデータロードを行うパッケージだったのですが、特筆すべき点として、レコードの依存関係を自動的に解決して順番にロードしてくれるという仕組みがありました。

つまり、以下のようなデータ群があるとして

Account

Id Name ParentId
a00001 株式会社初芝電機
a00002 株式会社初芝テクノロジー a00001
a00003 サニー株式会社

Contact

Id AccountId FirstName LastName
c00001 a00001 山田 太郎
c00002 a00001 鈴木 花子
c00003 a00002 佐藤 一郎
c00004 a00003 田中

第1フェーズでは、他のレコードへの参照依存のない a00001 および a00003 レコードを挿入し、新たなIDとしてそれぞれ A00001 および A00003 が割り当てられるとします。

第2フェーズでは、依存の解決したc00001c00002 および c00004 レコードと a00002レコードに対して、a00001 およびa00003 の参照IDをそれぞれ得られたA00001 および A00003に置き換えて挿入します。(ここでa00002のレコードの挿入結果として割り当てられたIDを A00002とします)

最後のフェーズで、残った c00003レコードに対して a00002 の参照IDをA00002に置き換えて挿入する、という形です。

当時、外部IDを利用した手作業が主体だったデータロード作業において、1クリックでさくっとデータロードが可能なのはなかなか便利だったと考えています。

その後、Visualforce環境でも利用できるように独自カスタマイズしたものを弊社内では利用していましたが、しかしながらさすがにそろそろメンテナンスがめんどくさくなってきたのと、やはりUIを介したものよりも自動化を念頭に置いたものがほしいなということで、移行を考えていました。

sfdx-migration-automatic の紹介

せっかくなのでSalesforce CLIのプラグインとして提供するのが一番ツールチェイン的に使いやすいと思い、作成したのがこちらです。

sfdx-migration-automatic

元となった「開発用デモデータ集」パッケージ自体、処理はJavaScriptで書かれていますので、ある程度のコードは再利用できたのですが、まあまあ書き直しました(TypeScript)。今回、レコードデータをロードする処理だけでなく、既存の組織内のレコードをCSVにダウンロードする処理も加えています。

※ なお類似の取り組みに ETCopyData というのがあります。ある程度開発をすすめてから気づいたのですが、あまり詳しく中身を見てませんが多分似たようなことをやっています。

インストール方法

$ sfdx plugins:install sfdx-migration-automatic

未署名のため確認メッセージが出ますが、y (yes) と入力することでインストールできます。

$ sfdx plugins
salesforcedx 45.5.0
sfdx-migration-automatic 1.4.2

で上記のように表示されればOKです。

利用方法

データのダンプ用コマンド automig:dump と、ダンプしたデータのロード用コマンド automig:load があります。

データのダンプ

--objects (-o) オプションで指定したオブジェクトのデータをCSVファイルでダウンロードします。--outputdir (-d) オプションでCSVファイルを保存するディレクトリを指定します。

$ sfdx automig:dump --objects Account,Contact,Opportunity,Task,Event --outputdir ./path/to/dir --targetusername yourname@yourdomain.example.org

オブジェクトAPI参照名の後に:relatedをつけると、対象のオブジェクトから抽出するレコードを他のレコードに関連しているものだけに限定できます。

  • 取引先の所有ユーザのみをダウンロード対象にする
$ sfdx automig:dump --objects Account,User:related -d ./path/to/dir -u yourOrgAlias
  • 商談に関連したTodoのみをダウンロード対象にする
$ sfdx automig:dump --objects Opportunity,Task:related -d ./path/to/dir -u yourOrgAlias

抽出したCSVファイルはBOM (Byte Order Mark)付きのUTF-8となります。これでExcelでダブルクリックで開いたときにちゃんと文字コードを認識してくれるのですが、場合によってはあまり好ましくない場合もありますので、その場合は --excludebom をオプションで付けるとBOMをつけずに保存してくれます。

データのロード

--inputdir (-d)オプションで、ロードされているCSVファイルのディレクトリを指定します。なお、すべてのCSVファイル名はオブジェクトのAPI参照名+.csvの形式である必要があります。

$ sfdx automig:load --inputdir ./path/to/dir --targetusername yourname@yourdomain.example.org

移入するデータについて、新規に作成するのではなく、すでにその組織にある既存のレコードを参照させたいケース(例:ユーザ、レコードタイプ)は多いかと思います。その場合は --mappingobjects(-m) オプションに既存のレコードにマップさせたいオブジェクト名とキーとなる項目名のペアを:でつなげて指定することで、既存のレコードに置き換えて参照させることが可能です。
(--mappingobjectsに指定したオブジェクトのレコードについてもCSVファイルとして対象のディレクトリにおいておく必要があることに注意して下さい)

$ sfdx automig:load -d ./path/to/dir -m User:FederationIdentifier,RecordType:DeveloperName -u yourOrgAlias

また、--deletebeforeload オプションを指定すると、ロード対象になっている該当のオブジェクトのレコードデータを組織内からすべてクリーンアップ(削除)してからロードを開始します。見ての通り危険なのでこちらはかなり注意してご利用下さい

$ sfdx automig:load -d ./path/to/dir --deletebeforeload -u yourOrgAlias

まとめ

まあそれなりに役に立つと思います。まだロードがうまくいかないときなどのデバッグが難しいので、もう少しそのへんをフレンドリーにしたいところです。なにか問題ありましたら https://github.com/stomita/sfdx-migration-automatic/issues までご報告お願いいたします。

余談: Salesforce CLIプラグインの開発について

なお今回Salesforce CLIのプラグイン開発初めてやりましたが、そのままJSforceのConnectionが使えてなかなか便利ですね。ただバージョンが少し古いので、自前でConnection作り直すのがいいと思います。

import { Connection } from 'jsforce';

// ...

const conn1 = this.org.getConnection(); // `--targetusername` で指定したユーザでの接続が取得できる
await conn1.request('/'); // トークンが失効している場合自動的にリフレッシュされる
const { accessToken, instanceUrl } = conn1;
const conn2 = new Connection({ accessToken, instanceUrl });
// 以下JSforceを利用して様々な処理
const { totalSize, records } = await conn2.query("SELECT Id FROM Account");
// ...

追記 (2019/3/27 0:36)

ついこの前、オフィシャルブログでこんなのでてましたね。みんなやりたいこと同じなのな。

Open Sourcing Salesforce Intra Org Data Migrator Tool (Datafall)

中間ファイルをもたせるか持たせないかの違いで、参照依存の解決については似たような感じだと思われます。
ただ、いまさらJavaでこのへんやるのつらい(個人的感想)し、マッピングファイルとか正直できるだけ書きたくないですよね…

18
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?