关于 experience-ui-bundle-deploy
该 Skill 为 Salesforce UI Bundle 项目提供按序部署与组织配置流程,适合负责应用上线的开发者。它明确处理部署、权限分配和架构读取之间的依赖,并对自助注册和数据导入要求事先征求确认。
主要功能
- 01按依赖顺序部署元数据
- 02构建 UI Bundle
- 03配置权限与用户角色
- 04按配置启用自助注册和社交登录
- 05支持可选数据导入
适用场景
- 01将 UI Bundle 项目部署到 Salesforce 组织
- 02为架构读取准备权限集
- 03配置 Experience 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 Bundle 应用
部署顺序至关重要:某一步的输出是下一步的前置条件
(先部署再获取架构;先配置权限再获取架构;先配置角色/自注册,
再获取访客用户必须看到的架构)。这是规范的设置顺序,
移植自参考脚本 org-setup.mjs。references/ 中的
org-setup.mjs 行引用用于说明移植来源(解释每条规则的由来),指向
该外部参考脚本——它们不是此技能随附的文件,因此运行这些步骤时
无需打开。
按顺序运行每个步骤。所有可选步骤都由文件是否存在决定:如果其 约定文件不存在,则正常跳过并继续——不要伪造配置。对于两个具有破坏性或 开销较大的步骤(自注册、数据导入),运行前先询问用户。
事先收集输入
从项目中读取以下信息;仅在缺少信息时询问用户:
- 目标 org —
--target-org的别名/用户名。如果不明显,请询问。 - 源根目录 — 运行
scripts/get-source-root.sh,根据sfdx-project.json(packageDirectories[0].path+/main/default)解析元数据 源目录。如果项目文件缺失或格式错误,该脚本会以非零状态退出。绝不要硬编码force-app/main/default。 org-setup.config.json(可选)— 用于驱动权限集分配、角色、 自注册和社交登录。缺失的键表示“跳过该步骤”。 **例外:**如果文件缺失,但permissionsets/中有需要分配的权限集, 不要静默跳过——应搭建配置文件,或收集等效输入(见步骤 4)。data-plan.json(可选,位于项目的data/目录中)— 文件存在时启用数据步骤。
步骤 1 — Org 身份验证(始终执行)
无条件前置条件;不能跳过。如果 org 已连接
(sf org display --target-org <org> --json 成功),则无需操作。否则:
sf org login web --alias <org>
登录失败会在部署前中止整个设置流程。
步骤 2 — 预部署 UI Bundle 构建
构建所有 UI Bundle,确保在部署元数据之前 dist/ 已存在(UI Bundle
实体部署的是构建后的输出)。对于 uiBundles/ 下的每个 Bundle 目录:
npm install
npm run build
在部署 UI Bundle 且 dist/ 缺失或源代码发生变化时运行。
步骤 3 — 部署元数据
如果已配置自注册:
- 先部署许可证预检查(见
references/license-checks.md)——它会以清晰且 指明许可证的消息阻止部署,而不是给出晦涩的失败信息。 - 将自注册配置文件添加到本地源的
networkMemberGroups中 — 应用assets/network-selfreg-xml-recipe.md中的 Edit 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:该命令依赖源跟踪来决定要部署的内容,而在未启用源跟踪的 org
(大多数非 scratch org)中,它会中止并提示 "This org does not have source-tracking enabled … specify
the files or a manifest to deploy."。传入 --source-dir 后,无论 org 是否启用了源跟踪,
都会部署同一套完整内容,也不会出现该提示。如果部署在启用了源跟踪的 org 上报告冲突,
则使用 --ignore-conflicts 重新运行——不要回滚或缩减部署范围。
不要手动构建 package.xml、组装 --metadata-dir mdapi zip,也不要以其他方式转换为
metadata-format——这些操作都不需要,也不属于此流程。
超时时间为 180s。必须在分配权限和获取架构之前完成部署——对象、字段和权限集 只有在部署后才会出现在 org 中。
步骤 3b — 设置站点注销 URL(由配置控制)
仅当 org-setup.config.json 顶层包含 logoutUrl 时运行。如果不存在,则干净地跳过并说明原因。非破坏性且幂等——无需询问。
在这里、部署之后运行(不要合并到部署中),因为平台会拒绝相对注销 URL(“The logout page URL must be an absolute URL.”),而已交付的站点相对路径(例如 /propertyrentalapp/)会以站点的 Experience Cloud 源为基准解析为绝对 URL——该源只有在站点部署后才存在。
重要性:如果站点没有 <logoutUrl>,正在注销的成员会被送到组织默认站点的登录页面——在多站点组织中,那是另一个社区,因此“退出”会跳到错误站点的登录页面。设置此项可将注销引回此站点(以访客身份重新加载)。
步骤:
-
读取配置中的
logoutUrl;不存在 → 跳过。 -
推导站点——运行
scripts/derive-site-name.sh(单个*.network-meta.xml;若为零个或存在歧义则跳过)。 -
解析、设置并部署——使用一条命令。 调用辅助程序,它会将值解析为绝对 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 视为需要明确说明的跳过,而非设置失败——继续其余设置,并告知用户在站点的“管理”设置中手动设置注销 URL。用法、退出码约定和端口来源:references/logout-url.md。
步骤 4 — 分配权限集
在 <packageDir>/main/default/permissionsets/ 下查找权限集。如果没有权限集,且未显式传入任何权限集,则跳过。
如果存在权限集,但缺少 org-setup.config.json,请勿默默跳过。 缺少配置会使每个查找到的权限集都解析为 skip,因此不会分配任何权限集,后续的 GraphQL 架构也会不完整(调用方缺少 FLS)。请改为协助用户提供分配信息——可以从 assets/org-setup.config.template.json 生成 org-setup.config.json,也可以收集每个权限集的受分配者输入,以便一次性运行。完整的架构与生成配置流程:references/config-scaffold.md。写入文件或执行分配前,请先确认用户意图——不要捏造受分配者。
否则,根据配置中的受分配者(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 — 分配角色(由配置控制)
仅当 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的基础名称),如果文件数量为零或多于一个,则以非零状态退出(存在歧义 — 停止)。 - 启用自行注册并重新部署网络文件 — 应用
assets/network-selfreg-xml-recipe.md中的 Edit B(设置selfRegistration=true,注入<selfRegProfile>),然后仅重新部署这一个文件。此操作具备幂等性 — 如果已启用,则跳过两步。(Edit A,即添加成员组,已在步骤 3 中完成。) - 创建 Account 和 NetworkSelfRegistration — 应用
assets/network-selfreg.apex(具备幂等性;两者都采用先查询再创建的方式;将 4a 和 4b 分别作为两次独立的sf apex run调用运行)。
第 6b 步 — 启用社交登录(受配置控制)
仅当 org-setup.config.json 中存在 socialLogin 块时运行。如果该块
不存在,loadSocialLoginConfig 会返回 null,并隐藏此步骤——应正常地不执行任何操作,
并明确说明这一点。此步骤不会造成破坏且具有幂等性(只会添加缺少的
链接/成员),因此——与自助注册和数据导入不同——无需事先询问。
此步骤会将站点配置的身份验证提供方(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;数量为零或存在歧义时停止)。社交登录需要站点来解析其AuthConfig。 - 启用“Allow standard external profiles” — 通过 Metadata API 部署
assets/Communities.settings-meta.xml(使用临时的最小项目;参见参考文档)。此项为必需设置,这样 SSO 注册处理程序才能在标准社区配置文件上创建用户;否则身份验证提供方会因用户插入失败并返回FIELD_INTEGRITY_EXCEPTION。出现“already active”警告时可跳过,不视为失败。 - 将身份验证提供方关联到站点的
AuthConfig— 原样运行assets/social-login-auth-providers.apex(替换<siteName>、<ProviderNamesList>、<ApiVersion>),以创建缺少的AuthConfigProviders关联记录,然后读取其|DEBUG|行(表格见参考文档)。此操作要么全部成功,要么全部不执行:如果任何已配置的authProviderNames条目都没有匹配的AuthProvider(OAuth)或SamlSsoConfig(SAML)记录,脚本会输出MISSING_PROVIDERS,且不关联任何提供方——请先在 Setup 中创建/修复这些记录。 已关联的提供方会跳过(具有幂等性)。 - 将社区成员配置文件添加到
NetworkMemberGroup— 解析 Network 和 Profile Id,并在不存在时创建成员关系(命令见参考文档中的sf data)。缺少此步骤时,通过 SSO 注册的用户会遇到NO_ACCESS: User was not authorized for the community。 - (可选)为社区用户分配
communityUserPermset— 仅在已配置时执行。授予ApiEnabled,使 SSO 创建的用户能够调用getCurrentUser()(/chatter/users/me)。
重要: 存在
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 架构 + 代码生成 + 最终构建