[Salesforce] JSforceを使ってコマンド一発で組織のプロセスを無効化/有効化する

全プロセスをコマンド一発で無効化/有効化するスクリプトを作りましたので共有します(TypeScriptにて実装)。
2021.07.19

Salesforce レコードデータの自動マイグレーションを行う sfdx-migration-automatic で紹介されている自動マイグレーションツール sfdx-migration-automatic を使うにあたり、事前にデータ移行先組織のプロセスビルダープロセス、トリガー、フローなどを無効化しておかないと、処理に非常に時間がかかったりエラーになることがあります。

ですので、プロセス、トリガー、フローの無効化/有効化を行いたいのですが、当社組織には○十件レベルのプロセスなどが存在しているため、Salesforce上から手作業でポチポチと無効化したり、元に戻したり(有効化)していられません。

そこで、全プロセスをコマンド一発で無効化/有効化するスクリプトを作りましたので共有します(TypeScript)1

shinchit/sf-switch: Salesforce のプロセスを一括オン・オフするスクリプト https://github.com/shinchit/sf-switch

使い方

準備

$ git clone https://github.com/shinchit/sf-switch.git
$ cd sf-switch/
$ cat > .env
DOMAIN=<login or test。本番組織ならloginを指定する>
SF_USERNAME=<操作対象のSF組織のログインID>
SF_PASSWORD=<操作対象のSF組織のパスワード>
$ npm i

実行

$ npx tsc
$ node switch.js --mode off    # プロセスビルダーを一括無効化
$ node switch.js --mode on     # プロセスビルダーを一括有効化

留意事項

本スクリプトは、一括無効化した後に一括有効化して元の状態に戻す、という使い方を想定しています。
この想定通りの使い方をするかぎりにおいて、本スクリプトは無効化前に有効化していたプロセスのバージョンを正しく有効化にて復旧させます。
例えば、あるプロセスがバージョン14まで存在している状態でバージョン13を有効化している場合、このスクリプトは無効化の後に有効化するとバージョン14ではなくバージョン13にて有効化します。

コード

メインコードである switch.ts は次の通りです。

import * as fs from "fs";
import * as yargs from "yargs";
import * as jsforce from "jsforce";
import * as dotenv from "dotenv";
dotenv.config({ path: __dirname+'/.env' });

// accept command line arguments
let { argv } = <any>{};
argv = yargs
  .option("mode", {
    description: "required. You have to specify running mode 'on' or 'off'",
    demandOption: false,
    default: "off"
  })
  .help().argv;

const DEFINITION_DATA_FILE_PATH = __dirname + '/data/' + process.env.SF_USERNAME + '_define.json';

(async () => {
  const conn = new jsforce.Connection({
    loginUrl : 'https://' + process.env.DOMAIN + '.salesforce.com'
  });
  await conn.login(process.env.SF_USERNAME, process.env.SF_PASSWORD);

  // fetch FlowDefinition using Tooling API
  const flowDefinitions = await conn.tooling.query('SELECT Id, ActiveVersion.VersionNumber, LatestVersion.VersionNumber, DeveloperName FROM FlowDefinition');
  let records: any[] = flowDefinitions['records'];
  if ( argv.mode === 'on' ) {
    if ( fs.existsSync(DEFINITION_DATA_FILE_PATH) ) {
      records = JSON.parse(fs.readFileSync(DEFINITION_DATA_FILE_PATH, 'utf8'));
    }
  } else {
    if ( ! fs.existsSync(DEFINITION_DATA_FILE_PATH) ) {
      fs.writeFileSync(DEFINITION_DATA_FILE_PATH, JSON.stringify(flowDefinitions['records'], null, 2));
    }
  }

  records.forEach(function(flow: any) {
    const activeVersionNumber = argv.mode === 'on' ? flow['ActiveVersion']['VersionNumber'] : null;
    const res = conn.tooling.sobject('FlowDefinition').update({
      Id: flow['Id'],
      Metadata: {
        'activeVersionNumber': activeVersionNumber
      }
    });
  });
})();

tooling API を使ってプロセスビルダーのプロセス(FlowDefinition)を取得し、

await conn.tooling.query('SELECT Id, ActiveVersion.VersionNumber, LatestVersion.VersionNumber, DeveloperName FROM FlowDefinition');

activeVersionNumbernull または 特定のバージョン番号 を設定して更新をかけています。

const res = conn.tooling.sobject('FlowDefinition').update({
  Id: flow['Id'],
  Metadata: {
    'activeVersionNumber': activeVersionNumber
  }
});

その他のソリューション

Toolkit for Salesforce にて、 Salesforce Switch というサービスが公開されています。
このサービスを使っても一括無効化/有効化ができるようです。
ただし、コードを読んでみたところ、このサービスでは無効化から有効化を行った時に、戻されるバージョンは無効化前のバージョンではなく、当該プロセスの最大のバージョンの値にて有効化されるようでした。

参考資料


  1. 本スクリプトの利用に関し、トラブルが発生した場合、利用者又は第三者に損害が生じた場合であっても、本スクリプトが利用者の自己責任のもと利用されるものであることに鑑み、弊社は、損害賠償その他一切の責任を負担致しません。