【Salesforce】複数の変更セットを楽して1つにまとめる

# はじめに

近年はSalesforce DXの台頭もあり、CLIによる自動化やGitによるソース管理など、リリースサイクルを見直している開発チームも多いのではないでしょうか。
しかし、元々ノーコード・ローコード開発を売りにしているSalesforceでは、まだまだ変更セットによるリリースが主流のようです。

変更セットによるリリース時、最も大変な作業の1つに「複数の送信変更セットをまとめて、1つの大きな送信変更セットを作成する」ことが上げられます。
複数のSandbox環境で作業している場合や、管理者が別々にリリースを行っている場合、全ての変更を別環境に反映させるのはかなり過酷な作業です。
しかし、画面上で複数の変更セットをマージすることはできないため、全てのコンポーネントをもう一度手作業で選択して新たに変更セットを作成する、という作業を行っている管理者の方がたくさん居るのではないでしょうか。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573865/d9688e65-c294-d643-af0a-4d71d1ffbce2.png)

そこで今回は、この地獄のような作業をなるべく楽に行える手順を紹介します。
一部コマンドラインによる操作が必要になりますが、なるべく噛み砕いて説明しますのでどうか最後までお付き合い下さい。

また記事の作成にあたり、全面的にこちらの記事を参考にさせていただきました。

https://qiita.com/atskimura/items/39b9eff9cfcdc77d0dc9

# 目次と要約
- [0. 事前準備](#0-事前準備)
- [1. 送信済の変更セットをダウンロードする](#1-送信済の変更セットをダウンロードする)
- [2. packageファイルを1つにまとめる](#2-packageファイルを1つにまとめる)
- [3. 組織のデータを取得する](#3-組織のデータを取得する)
- [4. データの形式を変換する](#4-データの形式を変換する)
- [5. zipファイルを作成する](#5-zipファイルを作成する)
- [6. 変更セットを作成する](#6-変更セットを作成する)

# 0. 事前準備
以下のツールをインストールして下さい。

- [Chrome拡張 ORGanizer for Salesforce](https://chrome.google.com/webstore/detail/organizer-for-salesforce/lojdmgdchjcfnmkmodggbaafecagllnh?hl=ja)（変更セットのダウンロード）
- [VSCode向け拡張機能 Salesforce Extension Pack](https://marketplace.visualstudio.com/items?itemName=salesforce.salesforcedx-vscode)（CLIコマンドの実行）
- [7-Zip](https://sevenzip.osdn.jp/download.html)（※Windowsユーザのみ、文字コードを指定してzipファイルを作成）

括弧内の動作が可能であれば、上記ツールでなくとも問題ありませんが、今回は上記のツールを用いて作業を進めます。

# 1. 送信済の変更セットをダウンロードする

最初に必要な作業は素材集めです。
対象の送信変更セット詳細画面へ移動して下さい。
ORGanizer for Salesforceが有効化されていれば、以下のようにダウンロードボタンが表示されます。
こちらをクリックするとzipファイルが取得できるので、この作業を各変更セットに対して行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573865/a54fabd6-2b6d-0eee-0eb4-ca9af319a5b3.png)

### ※注意点
ダウンロードするためには、**変更セットの名前が環境内で一意である**必要があります。
同じ名前の変更セットが複数存在した場合、いつまでもロードが終わらずダウンロードできません。
この状況に陥った場合は、変更セットの名前を一意に変更した上でコピーすればOKです。

# 2. packageファイルを1つにまとめる
ダウンロードしたzipファイルは以下のような構成になっています。

```
.
├── classes
│     ├── <Apexクラス>.cls
│     ├── <Apexクラス>.cls-meta.xml
│     └── ...
├── objects
│     ├── Account.object
│     └── ...
├── layouts
│     ├── ...
├── profiles
│     ├──...
.
.
└── package.xml

※各フォルダは変更セットに含む内容のみ
```

今回の手順では`package.xml`というファイルのみが必要です。
このファイルはSalesforce組織とやり取りを行う内容を定義するファイルです。
`<name>`にはコンポーネントの種類、`<members>`には個別のコンポーネント名が定義されています。

ダウンロードした各`package.xml`ファイルの`<types>～</types>`をコピーし、全てを1つにまとめて保存します。
この時、以下例のように重複する`name`や`members`があっても問題ありません。
無心でひたすらコピペするだけです。

```xml
<!-- ヘッダ部分は必須 -->
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <!-- 変更セット1つ目 -->
    <types>
        <members>AccountCreate</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>Account</members>
        <name>CustomObject</name>
    </types>
    <!-- 変更セット2つ目 -->
    <types>
        <members>AccountCreate</members>
        <members>AccountCreateTest</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>Account</members>
        <members>Contact</members>
        <name>CustomObject</name>
    </types>
    <!-- 変更セット3つ目 -->
    <types>
        <members>CommonUtility</members>
        <name>ApexClass</name>
    </types>
<!-- フッタ部分も必須 -->
    <version>48.0</version>
</Package>
```

# 3. 組織のデータを取得する
ここまでの手順で、複数の変更セットに定義されていたコンポーネントを1つにまとめた`package.xml`ファイルを作成できました。
次は作成したファイルを元に、組織からコンポーネントそのものを取得していきます。

## 3-1. プロジェクトを作成する
プロジェクトとはSalesforceとデータをやり取りする際に必要なフォルダと定義ファイルの構造体です。
今回は組織からコンポーネントを取得し、一時的に保管するために作成が必要です。

1. VSCodeのコマンドパレットを`Ctrl + Shift + P`で開き、`SFDX:プロジェクトを作成`を選択
1. 「標準」を選択 → プロジェクト名（任意のフォルダ名）を入力
1. フォルダ選択画面が立ち上がるので、任意のフォルダを選択し「プロジェクトを作成」を選択

作成されたプロジェクトには様々なフォルダやファイルが存在しますが、ここでは`force-app/main/default`以下のフォルダに注目して下さい。
こちらはプロジェクト内で管理するデータを管理する主要部分です。
すでに`classes`や`objects`などのフォルダが作成されていますが、中身は空の状態です。
この後組織からデータを取得すると、全てこのフォルダに格納されるという点だけ覚えておいて下さい。

## 3-2. 組織を認証する
プロジェクトの作成が完了したので、Salesforce組織を認証してデータのやり取りができる状態にします。

1. `Ctrl + Shift + P` → `SFDX:組織を認証`
1. ログインに使用するURLを選択
1. 組織のエイリアス（組織の別名）を任意入力
1. 立ち上がったブラウザでSalesforceへログイン

## 3-3. データを取得する
いよいよ組織からデータを取得します。
まずは手順2で作成した`package.xml`ファイルをルートディレクトリ（プロジェクトで一番上の階層）に配置します。
そしてVSCodeでターミナルを開き、以下のコマンドを実行して下さい。

```
sfdx force:source:retrieve -x ./package.xml
```

`-x ./package.xml`の部分で`package.xml`へのパスとファイル名を指定しています。
完了するとターミナルへ取得内容が出力されると同時に、`force-app/main/default`以下のフォルダにコンポーネントが配置されます。
これでデータの取得も完了です。

ここで`ERROR running force:source:retrieve:  'undefined' is not valid for the type xsd:double`が出力された場合は、閉じタグの不一致によるエラーの可能性が高いです。
`package.xml`を確認して修正を行って下さい。

### ※注意点
`package.xml`にカスタムオブジェクトそのものを記載してデータを取得した場合、カスタム項目・レイアウト・レコードタイプなど、対象のオブジェクトが包括するコンポーネントが全て自動で取得されます（ソース形式・メタデータ形式の違いによるもの。詳細は後述します）。
何か不都合が生じる場合は、送信変更セットに含めたくないコンポーネントを直接削除してから次の手順に進んで下さい。

# 4. データの形式を変換する
ここまでの手順で、`force-app`以下のフォルダに必要なコンポーネントが揃いました。
zipファイルを作成する下準備として、以下のコマンドでデータをソース形式からメタデータ形式へ変更します。

```
sfdx force:source:convert -p ./force-app/main/default -n <変更セット名> -d <出力するフォルダ名>
```

このコマンドを実行すると、プロジェクトに上記で指定した名前のフォルダが作成されます。
この中には`force-app`以下のフォルダと同じく、各コンポーネントのフォルダと`package.xml`が存在し、ファイルの`<fullName>`に先程指定した変更セット名が定義されています。

### ※補足（読み飛ばし可）
ここではカスタムオブジェクトのデータ構造について、ソース形式とメタデータ形式の違いを説明します。

・ソース形式

```
├── objects
│     ├── Account
│     │      ├── fields
│     │      ├── recordTypes
│     │      ├── listViews
│     │      └── ...
│     ├── Contact
│     │      ├── fields
│     │      ├── recordTypes
│     │      ├── listViews
│     │      └── ...
```


・メタデータ形式

```
├── objects
│     ├── Account.object
│     └── Contact.object
```

ご覧の通り、ソース形式では細かく内容が分割されているのに対して、メタデータ形式ではオブジェクト単位で1つのファイルにまとめられています。
手順3-3で紹介した注意点はこの形式の違いによるものです。

# 5. zipファイルを作成する
一見簡単そうに見えますが、Windowsユーザの方は注意が必要です。
というのも、zipファイルをSalesforceへ送信する場合、**文字コードをUTF-8へ変換する**必要があります。

zipファイルを右クリック → 圧縮を選択して後述するデプロイコマンドを実行すると、
`UNKNOWN_EXCEPTION: An unexpected error occurred. Please include this ErrorId if you contact support: xxxxx-xxxxx(xxxxx)`とエラーが出力されデプロイできません。

文字コードを指定したzip化する方法はいくつかありますが、ここでは [7-Zip](https://sevenzip.osdn.jp/download.html)を使用する方法を紹介します。
zipファイルを右クリック → 7-Zip → 「圧縮」を選択すると、ダイアログが立ち上がります。
ここで、「アーカイブ形式 → zip」「パラメーター → `cu=on`」と設定して圧縮を行うと、UTF-8形式でzipファイルを作成できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573865/ed43f76a-b486-e685-2e9a-b6479d7c457b.png)

# 6. 変更セットを作成する
いよいよ大詰めです。
まずは組織へログインし、手順4で指定した変更セット名を用いて空の送信変更セットを作成します。
その後VSCodeに戻り、以下のコマンドを実行してzipファイルをデプロイします。

```
sfdx force:mdapi:deploy -f ./<zipファイル名>.zip -w 15
```
ターミナルに進行状況が出力されるので、無事完了したことを確認してから変更セット詳細画面へ移動します。
コンポーネント一覧に指定した内容が全て含まれているはずです。

後はいつも通り対象の組織へアップロードすれば完了です！

# さいごに
ここまでお疲れ様でした！
想像より大変だったかもしれませんが、何千何百のコンポーネントを1つ1つ手作業で追加することを考えると、かなり作業が楽になったんじゃないかと思います。

本記事は以上となります。
最後までお付き合い下さりありがとうございました！

# 参考記事
[SFDXプロジェクトから変更セットを自動作成する
](https://qiita.com/atskimura/items/39b9eff9cfcdc77d0dc9)