如何在Salesforce第二代托管包(2GMP)中打包Custom Metadata Type?
问题概述
在构建第二代托管包(2GMP)时,已在开发者组织创建带自定义字段的Custom Metadata Type(CMDT),通过sf project retrieve start --metadata CustomMetadata检索后,创建包版本时Apex代码报错,提示CMDT不存在,具体错误包括:
- 变量
realWebhookTokens不存在 - 无效类型:
<REDACTEDNAMESPACE>__<REDACTED>_Webhook_Token__mdt - 测试类依赖的TriggerHandler因CMDT类型无效无法编译
- Connected App补丁版本因新增组件报错
CMDT用于存储仅同命名空间可访问的webhook令牌,通过动态序列化Trigger调用Handler查询令牌并发送请求。
解决方案
1. 修正CMDT的检索范围
--metadata CustomMetadata仅会检索CMDT的记录,不会包含CMDT的对象定义、自定义字段等核心元数据。需要同时检索CMDT类型本身:
# 同时检索CMDT类型和记录 sf project retrieve start --metadata "CustomMetadata,CustomMetadataType:<REDACTED>_Webhook_Token__mdt"
如果使用package.xml,需添加对应的节点:
<types> <members><REDACTED>_Webhook_Token__mdt</members> <name>CustomMetadataType</name> </types> <types> <members><REDACTED>_Webhook_Token__mdt.*</members> <name>CustomMetadata</name> </types>
2. 确保CMDT纳入包定义
检查sfdx-project.json的packageDirectories,确认CMDT的元文件(force-app/main/default/customMetadataTypes和force-app/main/default/customMetadata下的文件)都在包的目标路径内。
运行包版本创建命令时,指定正确的路径并确保包含所有依赖:
sf package version create --package "你的包名" --path force-app/main/default --version-number 1.1.0.NEXT
3. 校验命名空间与访问权限
- 确认Apex代码中CMDT的引用前缀正确(
<REDACTEDNAMESPACE>__<REDACTED>_Webhook_Token__mdt),且代码属于托管包的同一命名空间。 - 检查CMDT的可见性设置:在开发者组织中,CMDT的“可见性”需设为“仅在命名空间内可见”,同时Apex类的访问级别为
public或global(托管包代码必须用global或public)。
4. 解决动态调用的编译依赖
动态序列化调用可能导致编译时无法识别CMDT类型,需在TriggerHandler中添加显式引用(哪怕是占位符),确保编译器能解析依赖:
// 编译依赖占位符,避免类型无法识别 <REDACTEDNAMESPACE>__<REDACTED>_Webhook_Token__mdt tempToken = null;
测试类中如需访问CMDT,可通过元数据部署插入测试记录:
@isTest private class TriggerHandlerTest { static testMethod void testWebhook() { // 构建测试CMDT记录 CustomMetadata tempToken = new CustomMetadata(); tempToken.fullName = '<REDACTED>_Webhook_Token__mdt.Test_Token'; tempToken.label = 'Test Token'; // 设置自定义字段值 tempToken.put('<REDACTED>__Token__c', 'test_token_123'); // 部署测试元数据 Metadata.DeployContainer container = new Metadata.DeployContainer(); container.addMetadata(tempToken); Test.startTest(); Id deployId = Metadata.Operations.enqueueDeployment(container, null); Test.stopTest(); } }
5. 处理补丁版本的限制
错误中提到的Connected App补丁问题,是因为补丁版本不允许添加新组件(如新增CMDT、Connected App配置)。如果是首次将CMDT纳入包,需创建主版本(如从1.0.0升级到1.1.0),而非补丁版本(1.0.1)。
内容的提问来源于stack exchange,提问作者renepanke

