experience-ui-bundle-deploy について
Salesforce UI Bundle プロジェクトのデプロイと組織設定を順序立てて進めるスキルです。リリースを担う開発者向けに、メタデータ、権限、スキーマ取得の依存関係を扱い、自己登録やデータ取り込みの前には確認を求めます。
主な機能
- 01依存順にメタデータをデプロイ
- 02UI Bundle のビルド
- 03権限とユーザーロールの設定
- 04設定に応じた自己登録とソーシャルログイン
- 05任意のデータ取り込み
活用シーン
- 01Salesforce 組織へ UI Bundle をデプロイ
- 02スキーマ取得用の権限セットを準備
- 03Experience Cloud サイトのログインを設定
- 04データ計画に沿ってデータを取り込み
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill experience-ui-bundle-deployインストール後、Claude Code で/experience-ui-bundle-deployを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/Communities.settings-meta.xmldata-delete.apexdata-import.apexnetwork-selfreg-xml-recipe.mdnetwork-selfreg.apexorg-setup.config.template.jsonprepare-import-unique-fields.jssocial-login-auth-providers.apexreferences/config-scaffold.mddata-import.mddev-preview.mdgraphql.mdlicense-checks.mdlogout-url.mdrole-assignment.mdself-registration.mdsocial-login.mdscripts/derive-site-name.shfind-data-plan.shfind-prep-script.shget-source-root.shset-logout-url.mjs詳細
UI バンドルアプリのデプロイ
デプロイの順序は重要です。あるステップの出力が次のステップの前提条件になります
(スキーマ取得の前にデプロイ、スキーマ取得の前に権限設定、ゲストユーザーが参照するスキーマの前にロール/セルフ登録)。これは、リファレンスの org-setup.mjs から移植した標準的なセットアップ手順です。
references/ にある org-setup.mjs の行への引用は、移植元の根拠(各ルールが必要な理由)として外部のリファレンススクリプトを指しています。このスキルに同梱されたファイルではないため、手順の実行時に開く必要はありません。
各ステップを順番に実行してください。すべての任意ステップは、ファイルの有無に基づいて実行します。規約ファイルが存在しない場合は、設定を捏造せず、何もせずに次へ進んでください。破壊的またはコストのかかる2つのステップ(セルフ登録、データインポート)を実行する前に、ユーザーに確認してください。
事前に収集する入力
プロジェクトから以下を読み取ってください。不足している情報についてのみ、ユーザーに確認してください。
- 対象組織 —
--target-orgに指定するエイリアス/ユーザー名です。明らかでない場合は確認してください。 - ソースルート —
scripts/get-source-root.shを実行して、sfdx-project.jsonのメタデータソースディレクトリ(packageDirectories[0].path+/main/default)を解決してください。 プロジェクトファイルがない場合や形式が不正な場合、このスクリプトは 0 以外の終了コードで終了します。force-app/main/defaultをハードコードしないでください。 org-setup.config.json(任意) — 権限セットの割り当て、ロール、セルフ登録、ソーシャルログインを制御します。キーがない場合、そのステップは「スキップ」を意味します。 例外: ファイルがない一方で、permissionsets/に割り当て対象の権限セットがある場合は、黙ってスキップしないでください。設定ファイルをひな形から作成するか、同等の入力情報を収集してください(ステップ4を参照)。data-plan.json(任意。プロジェクトのdata/ディレクトリ内) — ファイルが存在する場合、データステップが有効になります。
ステップ1 — 組織の認証(常に実行)
無条件の前提条件であり、省略できません。組織がすでに接続済みの場合(sf org display --target-org <org> --json が成功する場合)は、何もせずに進みます。それ以外の場合:
sf org login web --alias <org>
ログインに失敗した場合は、デプロイの前にセットアップ全体を中止します。
ステップ2 — デプロイ前の UI バンドルのビルド
メタデータのデプロイ前に dist/ が存在するように、すべての UI バンドルをビルドしてください(UI バンドルのエンティティでは、ビルド済みの出力がデプロイされます)。uiBundles/ 配下にある各バンドルディレクトリについて、次を実行します。
npm install
npm run build
UI バンドルをデプロイする場合に実行してください。また、dist/ がない場合や、ソースが変更された場合にも実行してください。
ステップ3 — メタデータのデプロイ
セルフ登録が設定されている場合:
- 最初にライセンスの事前チェックをデプロイします(
references/license-checks.mdを参照)。これにより、分かりやすいライセンス名付きのメッセージでデプロイをブロックでき、原因不明のエラーを避けられます。 - ローカルソースの
networkMemberGroupsにセルフ登録プロファイルを追加します —assets/network-selfreg-xml-recipe.mdの 編集A を適用してください。プロファイルが認識済みサイトメンバーとしてデプロイされるよう、このデプロイの前に行う必要があります。ここでネットワークファイルだけを単独でデプロイしてはいけません(このデプロイに含まれます)。ベストエフォートで冪等に行い、すでにメンバーであればスキップしてください。
次に、解決済みのソースルートを --source-dir に指定して、プロジェクト全体(すべてのメタデータ)をデプロイします。
sf project deploy start --source-dir <sourceRoot> --target-org <org>
<sourceRoot> は scripts/get-source-root.sh の値です(例:
force-app/main/default)。必ず --source-dir を指定してください。パスを指定せずに sf project deploy start を実行してはいけません。このコマンドはソーストラッキングを基にデプロイ対象を決めますが、ソーストラッキングが有効でない組織(ほとんどの非スクラッチ組織)では、「この組織ではソーストラッキングが有効になっていません……デプロイするファイルまたはマニフェストを指定してください」というメッセージを出して中止します。--source-dir を渡すと、ソーストラッキングの有無にかかわらず、同じ一式をデプロイでき、このメッセージも表示されません。ソーストラッキングが有効な組織でデプロイ時に競合が報告された場合は、--ignore-conflicts を指定して再実行してください。デプロイ対象をロールバックしたり減らしたりしてはいけません。
package.xml を手作業で作成したり、--metadata-dir 用の mdapi zip を組み立てたり、その他の方法でメタデータ形式に変換したりしてはいけません。これらは不要であり、このフローには含まれません。
タイムアウトは180秒です。権限の割り当てとスキーマ取得の前に完了する必要があります。オブジェクト、項目、権限セットが組織に表示されるのは、デプロイ後です。
ステップ 3b — サイトのログアウト URL を設定する(config に応じて実行)
org-setup.config.json のトップレベルに logoutUrl がある場合のみ実行します。存在しない場合は何もせず、その旨を伝えてください。非破壊的で冪等なため、確認は不要です。
相対ログアウト URL はプラットフォームに拒否される(「ログアウトページ URL は絶対 URL である必要があります。」)ため、デプロイに含めず、デプロイ後にここで実行します。また、配布されたサイト相対パス(例:/propertyrentalapp/)は、サイトの Experience Cloud オリジンに対する絶対 URL として解決されます。このオリジンはサイトのデプロイ後にのみ存在します。
重要な理由:<logoutUrl> のないサイトでは、ログアウトするメンバーは組織のデフォルトサイトのログインページに移動します。複数のサイトがある組織では、これは別のコミュニティであるため、サインアウト後に誤ったサイトのログインページが表示されます。これを設定すると、ログアウト後にこのサイトへ戻り(ゲストとして再読み込みされ)ます。
手順:
-
config から
logoutUrlを読み取ります。存在しない場合はスキップします。 -
サイトを特定します —
scripts/derive-site-name.shを実行します(*.network-meta.xmlが 1 つの場合のみ。0 個または複数ある場合はスキップします)。 -
解決、設定、デプロイを 1 つのコマンドで行います。 ヘルパーを呼び出します。ヘルパーは値を絶対 URL に解決し(サイト相対 URL は、推測せずにコミュニティの
siteUrlのパスと照合します)、正規の位置に<logoutUrl>を冪等に書き込み、そのファイルのみをデプロイします。node scripts/set-logout-url.mjs \ --logout-url "<logoutUrl from config>" \ --network-file <sourceRoot>/networks/<site>.network-meta.xml \ --target-org <org> --site <site> --deploy
ベストエフォート: ヘルパーは成功時または設定済みの場合は 0、回復可能なスキップ(ネットワークファイルがない、オリジンを解決できない、XML 特殊文字が含まれる、デプロイに失敗した場合)は 3 で終了します。終了コード 3 はセットアップの失敗ではなく、明示的なスキップとして扱ってください。 セットアップの残りは続行し、サイトの Administration 設定でログアウト URL を手動設定するようユーザーに伝えてください。使い方、終了コードの仕様、ポートの由来については、references/logout-url.md を参照してください。
ステップ 4 — 権限セットを割り当てる
<packageDir>/main/default/permissionsets/ 以下の権限セットを検出します。権限セットがなく、明示的に渡されたものもない場合はスキップします。
権限セットがあるのに org-setup.config.json がない場合は、黙ってスキップしないでください。 config がないと、検出されたすべての権限セットが skip として解決されるため、何も割り当てられず、その後の GraphQL スキーマが不完全になります(呼び出し元に FLS がありません)。代わりに、割り当て情報をユーザーが指定できるよう支援してください。assets/org-setup.config.template.json から org-setup.config.json をひな形として作成するか、単発の実行用に権限セットごとの割り当て先を確認します。スキーマ全体とひな形作成の手順については、references/config-scaffold.md を参照してください。ファイルの書き込みや割り当てを行う前に意図を確認し、割り当て先を捏造しないでください。
それ以外の場合は、各権限セットを config の割り当て先(org-setup.config.json の permsetAssignments)に従って割り当てます。割り当て先には currentUser、guestUser、skip(デフォルトは skip)のいずれかを指定します。
sf org assign permset --name <permset> --target-org <org> [--on-behalf-of <guestUsername>]
- currentUser —
--on-behalf-ofを省略します。 - guestUser — まずサイトのゲストユーザー名を解決します(
references/self-registration.mdのゲストユーザーのセクションを参照)。サイトを特定できない場合、またはゲストユーザーを解決できない場合は、その理由を記録してその権限セットをスキップします。他の権限セットは中止しないでください。 - 「Duplicate … PermissionSet」および「not found … target org」は失敗ではなく、スキップとして扱います。
GraphQL イントロスペクションで正しいスキーマを返すために必要です(呼び出し元にはカスタム項目の FLS が必要です)。
ステップ 5 — ロールを割り当てる(config に応じて実行)
org-setup.config.json に role: { assignee: "currentUser", roleName: "<UserRole>" } がある場合のみ実行します。現在のユーザーへのロール割り当てにより、Experience Cloud のセルフ登録が機能するようになります。冪等です。ユーザーにすでにロールがある場合はスキップします。詳細と正確なクエリについては、references/role-assignment.md を参照してください。
ステップ 6 — セルフ登録を有効にする(設定で制御)— まず確認してください
org-setup.config.json に
selfRegistration: { selfRegProfile, accountName } がある場合のみ実行します。実行する前にユーザーに確認してください。 手順(詳細は references/self-registration.md を参照してください):
- ライセンスの事前確認(ソフトスキップ)— 組織にプロファイルのライセンスシートがない場合は警告してスキップします。これは失敗ではありません。
references/license-checks.mdを参照してください。 - サイトを特定する —
scripts/derive-site-name.shを実行します。サイト名(単一の*.network-meta.xmlのベース名)が出力されます。該当するファイルが 0 件または複数ある場合はゼロ以外の終了コードで終了します(特定できないため、停止してください)。 - セルフ登録を有効化し、ネットワークファイルを再デプロイする —
assets/network-selfreg-xml-recipe.mdの Edit B を適用し(selfRegistration=trueを設定し、<selfRegProfile>を挿入)、その 1 ファイルのみを再デプロイします。冪等です。すでに有効な場合は、両方をスキップしてください。(メンバーグループを追加する Edit A は、ステップ 3 で実施済みです。) - Account + NetworkSelfRegistration を作成する —
assets/network-selfreg.apexを適用します(冪等です。どちらもクエリしてから作成します。4a と 4b は、個別のsf apex run呼び出しとして実行してください)。
ステップ 6b — ソーシャルログインを有効にする(設定で制御)
org-setup.config.json に socialLogin ブロックがある場合にのみ実行します。ブロックが存在しない場合、loadSocialLoginConfig は null を返し、このステップは非表示になります。その場合は何もせず、その旨を明確に伝えてください。このステップは非破壊的で冪等(不足しているリンクやメンバーを追加するだけ)なので、セルフ登録やデータのインポートとは異なり、事前に確認する必要はありません。
サイトに設定されている Auth Providers(OAuth)と SAML SSO 設定をサイトにリンクし、組み込みのソーシャルログインコンポーネントが React のログインページにボタンを表示できるようにします。React(Site Container)サイトでは SSO 管理 UI が非表示のため、リンクは AuthConfig / AuthConfigProviders レコードを使ってプログラムで行います。Setup をクリックして進める方法では実行できません。詳細、サブステップ、ポートの由来については references/social-login.md を参照してください。
設定の形式(完全なスキーマについては references/config-scaffold.md を参照してください):
{ "socialLogin": {
"communityMemberProfile": "Customer Community User",
"authProviderNames": ["Google", "My_SAML_Provider"],
"communityUserPermset": "myapp_Guest_User_Api_Access"
} }
手順(参照ファイル org-setup.mjs の main() にあるソーシャルログインのステップと同じ順序です。このステップは、セルフ登録の後、データ/GraphQL のステップの前に実行されます):
assets/ のテンプレートをそのまま適用してください(セルフ登録/データのステップと同様です)。各サブステップで実行できるコマンドの全容については references/social-login.md を参照してください。
- サイトを特定する —
scripts/derive-site-name.shを実行します(*.network-meta.xmlは 1 件のみ)。該当なし、または複数候補がある場合は中止します。ソーシャルログインでは、AuthConfigを特定するためにサイトが必要です。 - 「Allow standard external profiles」を有効にする — Metadata API を介して
assets/Communities.settings-meta.xmlをデプロイします(使い捨ての最小限のプロジェクトから行います。詳細はリファレンスを参照してください)。SSO 登録ハンドラーが標準コミュニティプロファイルのユーザーを作成するために必要です。これがないと、Auth Provider によるユーザーの挿入はFIELD_INTEGRITY_EXCEPTIONで失敗します。「すでに有効」という警告は致命的ではないため、スキップしてかまいません。 - Auth Provider をサイトの
AuthConfigにリンクする —assets/social-login-auth-providers.apexをそのまま実行します(<siteName>、<ProviderNamesList>、<ApiVersion>を置き換えます)。不足しているAuthConfigProviders中間レコードが作成されます。その後、|DEBUG|行を読み取ります(表はリファレンスを参照してください)。これは全件または何も行わない処理です。設定されたauthProviderNamesの項目に一致するAuthProvider(OAuth)またはSamlSsoConfig(SAML)レコードがない場合、MISSING_PROVIDERSが出力され、リンクは作成されません。先に Setup で作成または修正してください。すでにリンク済みの Provider はスキップされます(冪等)。 - コミュニティメンバープロファイルを
NetworkMemberGroupに追加する — Network と Profile の Id を特定し、メンバーシップがない場合は作成します(sf dataコマンドについてはリファレンスを参照してください)。これがないと、SSO で登録されたユーザーはNO_ACCESS: User was not authorized for the communityエラーになります。 - (任意)コミュニティユーザーに
communityUserPermsetを割り当てる — 設定されている場合にのみ行います。ApiEnabledを付与することで、SSO で作成されたユーザーでもgetCurrentUser()(/chatter/users/me)を利用できるようになります。
IMPORTANT:
socialLoginブロックが存在するのにステップをスキップすると、サイレント失敗につながります。アプリのデプロイは正常に完了しますが、ログインページにソーシャルログインボタンは表示されず、その理由を説明するエラーもありません。黙ってスキップしないでください。ブロックがある場合はステップを実行するか、ブロックが存在しなかったことを明確に伝えてください。
ステップ 7 — データのインポート(存在する場合)— 先に確認する
最初に scripts/find-data-plan.sh を実行します。ゼロ以外の終了コードが返された場合は、このステップをスキップします。
確認を求めたりエラーにしたりせず、ステップ 8 に進んでください(簡潔に「データプランがないため、データのインポートをスキップします」と伝えてもかまいません)。プランがなければ、インポートするものはありません。
成功すると、プランのパスが出力されます(再帰的に検索するため、プロジェクトルートの data/ と
<packageDir>/main/default/data/ のどちらの構成も検出されます)。
存在する場合:データをインポートまたはクリーンアップする前に、必ずユーザーに確認してください。最初に既存のレコードが削除されます。テンプレートをそのまま適用し、Apex を独自に変更しないでください。
scripts/find-prep-script.shを実行します。成功した場合、アプリに同梱されているprepare-import-unique-fields.jsのパスが出力されるので、最初に実行してください。このスクリプトはレコードファイルに安定した一意のキーを付与して、再実行時の重複を防ぎます。 そのコピーが想定する方法で呼び出してください(インターフェースは異なる場合があります。references/data-import.mdを参照してください)。終了コードがゼロ以外の場合は、準備スクリプトがないため、クリーンアップの手順に進んでください。assets/data-delete.apexを使って、プランの逆順(子レコードから親レコードの順)にクリーンアップします。assets/data-import.apexを使って、プランの順にインポートします。@referenceIdの参照を解決し、実測したサイズに基づいてバッチ処理します。
プロトコル、@referenceId の解決、実測サイズに基づくバッチ処理、および SETUP_RESULT_JSON の解析と失敗時の即時停止ルールについては、references/data-import.md を参照してください。
ステップ 8 — GraphQL スキーマの取得とコード生成
UI バンドルのディレクトリで、デプロイと権限の割り当てが完了した後に実行します(スキーマには組織の状態と呼び出し元の FLS が反映されます)。
npm install
SF_TARGET_ORG=<org> npm run graphql:schema
npm run graphql:codegen
npm run build
詳細については references/graphql.md を参照してください。オブジェクト、項目、または権限が変更されたデプロイのたびに、スキーマの取得とコード生成を再実行してください。
完了
セットアップはここで終了です。上記の手順(設定によって実行される 6b のソーシャルログインを含む)ですべて完了です。ローカル開発プレビュー(npm run dev:preview)はセットアップの一部ではなく、開発者が別途実行する操作です。サイトのプレビューを求められた場合は、references/dev-preview.md を参照してください。
重要なルール
- スキーマを取得する前にメタデータをデプロイしてください。カスタムオブジェクトとカスタム項目が表示されるのは、デプロイ後のみです。
- スキーマを取得する前に権限を割り当ててください。割り当てないと、呼び出し元が FLS を持たない可能性があります。
- オブジェクト、項目、または権限が変更されたメタデータのデプロイのたびに、スキーマの取得とコード生成を再実行してください。
- 権限の割り当て、セルフ登録、ソーシャルログイン、データのインポートを、気づかれないままスキップしないでください。規約ファイルまたは設定ブロックが存在する場合は(破壊的な操作については先に確認して)実行し、存在しない場合は問題なくスキップし、その旨を伝えてください。存在する
socialLoginブロックをスキップすると、説明エラーが出ないままログインボタンが表示されなくなります。 sfdx-project.jsonからソースパスを特定してください。force-app/main/defaultをハードコードしないでください。assets/の Apex テンプレートと XML テンプレートをそのまま適用してください。これらには、重複ルールのバイパス、allOrNone=falseによる削除、冪等性、SOQL の安全性、および(ソーシャルログイン用の)全件事前チェックと、AuthConfigProvidersへの DML が許可されていない場合に REST コールアウトで挿入する処理が組み込まれています。これらは手作業では間違えやすいものです。
操作順(概要)
- 組織を認証する
- UI バンドルをビルドする(デプロイ前)
- メタデータをデプロイする(セルフ登録が設定されている場合はデプロイライセンスの確認)
3b. サイトのログアウト URL を設定する(
logoutUrlが設定されている場合。デプロイ後、冪等、ベストエフォート) - 権限セットを割り当てる(設定に基づく割り当て先)
- ロールを割り当てる(設定されている場合)
- セルフ登録を有効にする(設定されている場合。先に確認する)
6b. ソーシャルログインを有効にする(
socialLoginが設定されている場合。冪等で、確認不要) - データをインポートする(データプランが存在する場合。先に確認する)
- GraphQL スキーマを取得してコードを生成し、最後にビルドする