『Salesforceの本番組織からApexクラスを、もっと!もっと!楽に削除したい!!!』ってお話です。
ことの発端
開発用のDE組織やSandbox組織と比べて、Salesforceの本番組織からApexクラスファイルを削除する時、公式サイトをみるとAnt 移行ツールを使った例が出てきたり、検索するとJSforce Metadata Toolsを利用する例やらWorkbenchを利用する例やら色々と出てきます。
本番組織からApexクラスファイルを削除するという作業は、基本的にやりたくない行為ではありますが、パッケージをインストールした時に、そのパッケージが自動生成したApexクラスなどが邪魔して、アンインストールするときに指定のApexクラスを削除しなければアンインストールできません!!って言うのですよね。
私には、(わざわざ追加でツールをインストールするしか方法がないのか・・?)と感じる方法ばかり目についてしまい、諦めてAnt移行ツールを使う方針で作業進めていたところ、颯爽とやってきた上司に『今はSFDXコマンドで対応できるようになっているよ!調べてみたら?』という、ありがたい助言を受けました。
その後、私自身が(アァ。。。コレ楽ダ。。)と感じたsfdx force:mdapi:deploy
コマンドを利用する方法を忘れないようにここに残します。
前提
普段からSFDXコマンドを利用した開発をしている人向けとなっております。
(※注意※SFDXコマンドは、Salesforce CLIツールである)
この環境がない人は『結局ツールを追加でインストールするの必要じゃねーか!!』となると思います。
せめて、Salesforce CLIツールの使い方だけ覚えるだけでも良いかもしれないです。
Salesforce CLI 設定ガイドを参考にSalesforce CLI をインストールされてください。
// 以下コマンドが実行できる環境が必要です。
sfdx --version
■VSCodeを使った環境構築をしたい人は...
VSCodeでSFDXコマンドを使った環境構築は、Trailheadのプロジェクト「クイックスタート: Salesforce 開発のための Visual Studio Code」 や @shunkosa さんの書いたQiita記事Visual Studio Code で Salesforce の開発環境を構築するが非常に参考になります。
やり方
ひとことで言うとdestructiveChanges.xml
という名前の削除マニフェストファイルを事前に定義しsfdx force:mdapi:deploy
コマンドを実行するだけです。
1.以下のようにフォルダを1つ作成し、その中に以下2つのファイルを作成します
removepkg // 任意のフォルダ
├── destructiveChanges.xml // XMLファイル
└── package.xml // XMLファイル
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<version>54.0</version>
</Package>
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>削除したいApexクラス名1</members>
<members>削除したいApexクラス名2</members>
<name>ApexClass</name>
</types>
<version>54.0</version>
</Package>
※このファイルの意味や書き方は、以下を参考にしてください。
組織からのファイルの削除 | Ant 移行ツールガイド | Salesforce Developers
>なぜ?Ant 移行ツールガイドなの?
ローカルPC上に存在するXML メタデータファイル(指令書みたいなもの)をSalesforce組織にアップロードして実行させるツールです。これと同じことはSFDXコマンドのsfdx force:mdapi:deploy
でも対応できます。メタデータファイルの書き方として仕組みが同じであるため、Ant 移行ツールガイドのリンクを紹介しました。
>他の書き方もあるの?
SFDXプロジェクト上で SFDXコマンドを実行する環境が整っているのであれば、コマンド「sfdx force:source:manifest:create -m ApexClass:削除したいApexクラス名 --manifesttype destroy
」実行でも自動生成できます。
2.sfdx force:mdapi:deploy
コマンドを実行してファイルを削除します
sfdx force:mdapi:deploy --deploydir removepkg \
--targetusername <Salesforce組織へのログイン可能なユーザIDもしくはエイリアス> \
--testlevel RunLocalTests \
-w 5
-
引数1つ目の
--deploydir
では実行するメタデータファイルが存在しているフォルダを指定します。
ここでは事前準備で作成したremovepkg
を指定してます。この名前は任意に変えること可能です。 -
引数2つ目の
--targetusername
は組織へログイン可能な権限を持つユーザーのIDもしくは事前に名前付きで認証をしているならば組織のエイリアス名を指定します。 -
引数3つ目の
--testlevel
では、組織に情報をデプロイ時のテストを実行するかどうかのフラグです。本番組織から直接Apexクラスファイルを削除する際は、最低でもローカルテストの実行必須です。NoTestRun
を指定すると、エラーメッセージERROR running force:mdapi:deploy: INVALID_OPERATION: testLevel of NoTestRun cannot be used in production organizations
が発生するのでRunLocalTests
を指定しましょう。 -
引数4つ目の
-w
はコマンドの実行待機時間(分)です。今回は5分と指定しておりますが、テスト実行に時間がかかるような組織の場合は、それに合わせて長めに時間を指定しましょう。 -
\
は長いコマンドを入力する際に改行して見やすくするために利用しているので、以下のように一行で実行しても問題ないです。(Linux、Mac系のターミナルの文化かも)sfdx force:mdapi:deploy --deploydir removepkg --targetusername <Salesforce組織へのログイン可能なユーザIDもしくはエイリアス> --testlevel RunLocalTests -w 5
sfdx force:mdapi:deploy
コマンドの詳細は以下公式サイトのリファレンスをご確認ください。
mdapi Commands | Salesforce CLI Command Reference | Salesforce Developers
以上!!
(余談)その他にも...※加筆※
SFDXコマンドを使ったApexクラスファイルの削除は、他にもsfdx force:source:retrieve
、sfdx force:source:deploy
を使う方法があります。
このやり方の大前提として、SFDXプロジェクト上で SFDXコマンドを実行する環境が整っている必要があります。
もし、SFDXプロジェクトが存在しない場合は、先に以下のコマンドを実行して環境をローカル上に作ってください。
// SFDXプロジェクトを作成
sfdx force:project:create --projectname <SFDXプロジェクト名(フォルダ名)>
// 制御したいSalesforce組織にログインしておく
sfdx auth:web:login -a <ログインしたSalesforce組織に別名付与>
(詳細みたければ、ここ展開してね)`sfdx force:source:retrieve`や`sfdx force:source:deploy`を使う具体的なやり方は以下の通りです。
まずsfdx force:source:retrieve
コマンドを実行して、ローカル環境にApexクラスファイルを落としてくる。
// 実行するコマンド
sfdx force:source:retrieve -m "ApexClass:削除したいApexクラスファイル" -u <Salesforce組織へのログイン可能なユーザIDもしくはエイリアス>
// コマンド結果
Preparing retrieve request... done
=== Retrieved Source
FULL NAME TYPE PROJECT PATH
────────────────── ───────── ──────────────────────────────────────────────────────────────
SVE_20150409121815 ApexClass force-app/main/default/classes/削除したいApexクラスファイル.cls
SVE_20150409121815 ApexClass force-app/main/default/classes/削除したいApexクラスファイル.cls-meta.xml
ローカルに落ちてきたApexクラスファイルの.cls-meta.xml
ファイルを開き、<status>Active</status>
を<status>Deleted</status>
に変更。
そして、sfdx force:source:deploy
コマンドを実行すると、ファイルが削除されます。
// 実行するコマンド
sfdx force:source:deploy -p "force-app/main/default/classes/削除したいApexクラスファイル.cls" -l RunLocalTests -u <Salesforce組織へのログイン可能なユーザIDもしくはエイリアス>
// コマンド実行結果
Deploy ID: XXXXXXX
=== Deployed Source
FULL NAME TYPE PROJECT PATH
────────────────── ───────── ──────────────────────────────────────────────────────────────
SVE_20150409121815 ApexClass force-app/main/default/classes/削除したいApexクラスファイル.cls
SVE_20150409121815 ApexClass force-app/main/default/classes/削除したいApexクラスファイル.cls-meta.xml
=== Test Results Summary
Passing: NN
Failing: 0
Total: NN
Time: 0
SFDXプロジェクトが存在しており、ソース管理しているなら、こちらの方法が早いかもしれません。
ただし、こちらの方法は依存しているファイルが存在していてもエラーメッセージが表示されず処理は成功とレスポンスが返ってきます。
そのためコマンドは成功しても、削除できないという現象が発生してしまい、原因分からずジレンマに陥りました。
記事公開後、さらに助言をうけ追加で分かったことがありましたので以下加筆しました。
そのほか、sfdx force:source:deploy
に引数--postdestructivechanges
を付与して削除する方法があります。
(詳細みたければ、ここ展開してね)`sfdx force:source:deploy --postdestructivechanges`を使う具体的なやり方は以下の通りです。
まず、以下を実行して削除用のマニフェストファイル(=destructiveChanges.xml)を自動生成します。
sfdx force:source:manifest:create -m ApexClass:削除したいApexクラス名 --manifesttype destroy
この時、package.xmlは自動生成されないので、上記で紹介しいるのと同じように自作します。
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<version>54.0</version>
</Package>
そして以下コマンドを実行します。
sfdx force:source:deploy --manifest package.xml --postdestructivechanges destructiveChanges.xml -l RunLocalTests -u <Salesforce組織へのログイン可能なユーザIDもしくはエイリアス>
postdestructivechanges引数を利用するときは、manifest引数必須です。
詳細は、SFDXコマンドの--help
を利用しつつ、公式サイトを確認しながら実行してください。
sfdx force:source:deploy
コマンドの詳細は以下公式サイトのリファレンスをご確認ください。
source Commands | Salesforce CLI Command Reference | Salesforce Developers
こちらの方法は、SFDXプロジェクトが存在しており、ソース管理しているなら、上記のsfdx force:source:retrieve
が不要なので、さらに楽できます!
なお、依存関係ある場合、Deploy failed.
とレスポンスがあり、失敗していることが分かりやすいです。
...しかし、大変残念な事に何が原因でエラーが発生しているのか等の詳細な情報は何故か出力されません。
そのためコマンドは失敗して削除できない。かつ失敗原因は分からず。という動きをする事がわかりました。
この引数postdestructivechanges
が提供されたのは、つい最近のv53(Winter '22)のリリースです。
よって、まだまだ発展途上なのかもしれません。今後に期待しつつ、いつかのリリースで改善されるかもしれませんね。
以上のことから、原因不明のエラー発生時はsfdx force:mdapi:deploy
コマンドを利用するのが当面のお勧めかもしれません。
まとめ
以上!!!
普段からSFDXコマンドに慣れ親しんでいる人向けの、おすすめ紹介でした(*´ `)
ではでは。