salesforce学习笔记(5)- Salesforce中的部署方式

无论你的项目用什么开发语言,都离不开部署这件事,今天我们就聊聊Salesforce中的部署方式。

我本人常用的部署方式有三种:更改集(Change Set)、Workbench、ANT(Force.com migration tool)

1、更改集(Change Set)

更改集应该是日常开发中最常用的部署方式,小规模开发或对象及字段的更改等,使用更改集部署比较方便快捷。但是,更改集仅用于在连接的组织中部署。

更改集有两种:

  • 入站更改集
  • 出站更改集

我们以开发环境和生产环境为例,开发环境的出站更改集进行上载,生产环境的入站更改集进行对上载的集合(或者理解为包)进行对应部署。

1.1、开发环境出站更改集的配置与上载

开发环境上载完成后,会受到提示。

1.2、生产环境入站更改集进行部署

生产环境进行验证和部署后,部署状态显示已成功。当然,在生产环境部署Apex代码时,要运行对应的测试类。由于更改集大家都很熟悉,这里就不过多赘述。

2、Workbench

先简单介绍一下Workbench:

Workbench是Salesforce官方提供的一个在线工具,用来帮助开发人员(包括集成)、管理员更轻松地与Salesforce实例交互、管理和测试。它提供了许多功能,包括API调用、数据查询、数据加载、元数据检查、日志分析等。

以下是Salesforce Workbench的主要特点:
1. **API调用**: Workbench允许用户直接在浏览器中进行Salesforce API的调用。这使得用户能够在不编写代码的情况下测试API端点、验证数据格式等。
2. **数据操作**: 用户可以使用Workbench执行各种数据操作,包括创建、读取、更新和删除记录。这对于在Salesforce中进行数据迁移、数据清理或数据验证非常有用。
3. **元数据检查**: Workbench允许用户检查Salesforce实例中的元数据,包括对象、字段、布局、工作流规则等。这对于了解实例配置、识别潜在问题或进行比较分析非常有帮助。
4. **日志分析**: 用户可以使用Workbench查看Salesforce实例中的日志,并分析执行过程中的事件和错误。这对于调试和优化代码或集成非常有用。

页面如下,链接地址请跳转

下面进行具体操作。

2.1、使用workbench从Salesforce中检索&获取元数据

步骤1:例如,我的环境中有个自定义对象:主环境测试对象(MainObj__c)。想通过workbench从Salesforce中检索&获取元数据,需要使用xml文件操作,package.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>MainObj__c</members>
        <name>CustomObject</name>
    </types>
    <version>58.0</version>
</Package>

步骤2:然后,操作workbench

步骤3:下载&解压后,文件夹结构如下:

上述【objects】📂打开后是下面文件:

MainObj__c对象的元数据(Metadata)

<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <actionOverrides>
        <actionName>Accept</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Accept</actionName>
        <formFactor>Large</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Accept</actionName>
        <formFactor>Small</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>CancelEdit</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>CancelEdit</actionName>
        <formFactor>Large</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>CancelEdit</actionName>
        <formFactor>Small</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Clone</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Clone</actionName>
        <formFactor>Large</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Clone</actionName>
        <formFactor>Small</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Delete</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Delete</actionName>
        <formFactor>Large</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Delete</actionName>
        <formFactor>Small</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Edit</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Edit</actionName>
        <formFactor>Large</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Edit</actionName>
        <formFactor>Small</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>List</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>List</actionName>
        <formFactor>Large</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>List</actionName>
        <formFactor>Small</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>New</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>New</actionName>
        <formFactor>Large</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>New</actionName>
        <formFactor>Small</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>SaveEdit</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>SaveEdit</actionName>
        <formFactor>Large</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>SaveEdit</actionName>
        <formFactor>Small</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Tab</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Tab</actionName>
        <formFactor>Large</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>Tab</actionName>
        <formFactor>Small</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>View</actionName>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>View</actionName>
        <formFactor>Large</formFactor>
        <type>Default</type>
    </actionOverrides>
    <actionOverrides>
        <actionName>View</actionName>
        <formFactor>Small</formFactor>
        <type>Default</type>
    </actionOverrides>
    <allowInChatterGroups>true</allowInChatterGroups>
    <compactLayoutAssignment>SYSTEM</compactLayoutAssignment>
    <deploymentStatus>Deployed</deploymentStatus>
    <enableActivities>true</enableActivities>
    <enableBulkApi>true</enableBulkApi>
    <enableFeeds>false</enableFeeds>
    <enableHistory>true</enableHistory>
    <enableLicensing>false</enableLicensing>
    <enableReports>true</enableReports>
    <enableSearch>true</enableSearch>
    <enableSharing>true</enableSharing>
    <enableStreamingApi>true</enableStreamingApi>
    <externalSharingModel>Private</externalSharingModel>
    <fields>
        <fullName>ExternalObj__c</fullName>
        <externalId>false</externalId>
        <label>测试用外部对象</label>
        <length>255</length>
        <referenceTo>ExternalObj_c__x</referenceTo>
        <relationshipLabel>主环境测试对象</relationshipLabel>
        <relationshipName>ExternalObj0wgJ</relationshipName>
        <trackHistory>false</trackHistory>
        <trackTrending>false</trackTrending>
        <type>ExternalLookup</type>
    </fields>
    <fields>
        <fullName>WorkbenchField__c</fullName>
        <externalId>false</externalId>
        <label>Workbench测试字段</label>
        <length>255</length>
        <required>false</required>
        <trackHistory>false</trackHistory>
        <trackTrending>false</trackTrending>
        <type>Text</type>
        <unique>false</unique>
    </fields>
    <label>主环境测试对象</label>
    <listViews>
        <fullName>All</fullName>
        <filterScope>Everything</filterScope>
        <label>全部</label>
    </listViews>
    <nameField>
        <label>主环境测试对象名称</label>
        <trackHistory>false</trackHistory>
        <type>Text</type>
    </nameField>
    <pluralLabel>主环境测试对象</pluralLabel>
    <searchLayouts/>
    <sharingModel>ReadWrite</sharingModel>
    <visibility>Public</visibility>
</CustomObject>

当然,也可以用类似于下面的文件,取得对象中某一字段的具体数据:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>MainObj__c.WorkbenchField__c</members>
        <name>CustomField</name>
    </types>
    <version>58.0</version>
</Package>
2.2 使用workbench部署取元数据
2.2.1 从一个环境部署到另一个环境(部署对象、Apex等的操作方法一样)

步骤1:假设,主环境中有一个自定义对象:

步骤2:主环境创建软件包,并将上述自定义对象添加到软件包

步骤3:用主环境账号登录Workbench,导出上述自定义对象的元数据

步骤4:将步骤3导出的元数据下载,Logout workbench后,用外部环境再次登录workbench,导入外部环境

步骤5:去外部环境验证部署结果

2.2.2 非不同环境间部署,只操作一个环境的话,可以直接作成文件,然后直接通过workbench,部署到该环境中

步骤1:自创建部属用文件

<!-- package.xml文件 -->
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>WbDeployObj__c.WbField1__c</members>
        <name>CustomField</name>
    </types>

    <version>58.0</version>
</Package>
<!-- Object_c.object文件 -->
<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
    <fields>
        <fullName>WbField1__c</fullName>
        <encryptionScheme>None</encryptionScheme>
        <externalId>false</externalId>
        <label>WB单一追加字段</label>
        <length>100</length>
        <required>false</required>
        <trackHistory>false</trackHistory>
        <trackTrending>false</trackTrending>
        <type>Text</type>
        <unique>false</unique>
    </fields>
</CustomObject>

步骤2:导入

步骤3:去环境中检验部署结果

3、ANT(Force.com migration tool)

ANT 迁移工具是一个命令行实用工具,用于从 Salesforce 实例检索、部署和删除元数据。它帮助我们在不同的 Salesforce 实例之间迁移元数据组件,例如 Apex Classes、Visualforce、SObject 等组件。

3.1 使用 ANT 迁移工具的优点
  • 元数据备份:从 Salesforce 组织获取 XML 文件形式的元数据,并将其下载到本地计算机上。
  • 删除组件:更改集不允许从目标组织中删除任何元数据组件(metadata component)。但是使用 ANT 迁移工具,可以从目标组织中删除组件。这可以使用 destructiveChanges.xml 文件来完成。
  • 组件支持:某些组件不支持使用更改集进行迁移,但可以使用 ANT 迁移工具来迁移它们。
  • 命令行支持:还可以使用一些特定命令来调用 API。
3.2 ANT 迁移工具和更改集之间的差异
ANT 迁移工具(ANT Migration Tool)更改集(Change Set)
用户界面ANT 迁移工具支持命令行界面,需要使用 Ant 脚本和 `build.xml` 文件来指定要取得/部署的元素。更改集是基于 UI 的部署工具,可在 Salesforce 组织中的设置中找到。使用 Setup > Deploy > Outbound / Inbound ChangeSets。
删除组件使用 ANT 迁移工具,可以从目标组织中删除组件更改集不允许从目标组织中删除任何元数据组件。
自动化支持通过在工具如 Jenkins 等中执行脚本来自动化部署。仅支持在沙盒之间或沙盒与生产环境之间手动部署。
依赖关系所有依赖关系都需要手动添加。依赖关系可以通过单击轻松添加。
持续部署适用于大型团队,支持连续部署。适用于中等规模的团队,使用连接的组织。
不同组织可以在不相关的 Salesforce 组织中部署组件。更改集仅允许在相关的组织和沙盒中部署组件。

两者都可以用于几乎任何事情的部署。如果部署规模较小,会使用更改集;但对于较大的部署(以及大型项目的首次部署),我们更推荐Ant(迁移工具)。
原因:在更改集中,如果必须为某个对象部署 100 个字段,在上传到其他环境之前,我们必须单独选择要添加到变更改中的每个字段。考虑一下如果有 10-15 个这样的对象,这极其耗时且容易出错。通过Ant,我们要做的就是在XML中提及对象,所有字段都会自动部署。
另外,如果必须删除生产中的组件,可以选择通过 ANT(Destructive.XML) 来完成,而更改集中没有这样的选项。
最后,更改集仅用于在连接的组织中部署,而通过 ANT 您可以在任何组织中部署。

 3.3 配置Ant迁移工具

步骤1:安装Java

建议使用 Java 版本 11 或更高版本(java -version)

步骤2:下载ANT工具(免安装)
Apache Ant - Binary Distributions

步骤3:下载Ant迁移工具(免安装)
Salesforce Developers

 注意,解压缩后,将[salesforce_ant_59.0]中的[ant-salesforce.jar]文件复制&粘贴到[apache-ant-1.10.14-bin]中\lib文件夹下

步骤4:设置路径(只设置用户变量即可)

ANT_HOME : ANT的位置.

JAVA_HOME : JDK的位置(where java)

Path : 设置Ant的位置(需要到bin文件夹)

配置以后,检查java和Ant的版本

步骤5:配置Build.xml文件和Build.properties文件

要设置与 salesforce 的连接,我们需要配置“ build.properties

# build.properties
#

# Specify the login credentials for the desired Salesforce organization
sf.username = 你的Salesforce用户名
sf.password = 你的密码
#sf.sessionId = <Insert your Salesforce session id here.  Use this or username/password above.  Cannot use both>
#sf.pkgName = <Insert comma separated package names to be retrieved>
#sf.zipFile = <Insert path of the zipfile to be retrieved>
#sf.metadataType = <Insert metadata type name for which listMetadata or bulkRetrieve operations are to be performed>

# Use 'https://login.salesforce.com' for production or developer edition (the default if not specified).
# Use 'https://test.salesforce.com for sandbox.
sf.serverurl = https://login.salesforce.com

sf.maxPoll = 20
# If your network requires an HTTP proxy, see http://ant.apache.org/manual/proxy.html for configuration.
#
<!-- build.xml文件-->
<project name="Sample usage of Salesforce Ant tasks" default="test" basedir="." xmlns:sf="antlib:com.salesforce">

    <property file="build.properties"/>
    <property environment="env"/>

    <!-- Setting default value for username, password and session id properties to empty string 
         so unset values are treated as empty. Without this, ant expressions such as ${sf.username}
         will be treated literally.
    -->
    <condition property="sf.username" value=""> <not> <isset property="sf.username"/> </not> </condition>
    <condition property="sf.password" value=""> <not> <isset property="sf.password"/> </not> </condition>
    <condition property="sf.sessionId" value=""> <not> <isset property="sf.sessionId"/> </not> </condition>

    <taskdef resource="com/salesforce/antlib.xml" uri="antlib:com.salesforce">
        <classpath>
            <pathelement location="../ant-salesforce.jar" />                
        </classpath>
    </taskdef>

    <!-- Shows deploying code & running tests for code in directory -->
    <target name="deployCode">
      <!-- Upload the contents of the "codepkg" directory, running the tests for just 1 class -->
      <sf:deploy username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="codepkg" testLevel="RunSpecifiedTests" rollbackOnError="true">
               <!-- 这里必须要填!!!否则出现错误: You must provide at least one test to run -->
               <runTest>AccountHandlerTest</runTest>
      </sf:deploy>
    </target>

    <!-- Shows retrieving code; only succeeds if done after deployCode -->
    <target name="retrieveCode">
      <!-- Retrieve the contents listed in the file codepkg/package.xml into the codepkg directory -->
      <sf:retrieve username="${sf.username}" password="${sf.password}" sessionId="${sf.sessionId}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" retrieveTarget="codepkg" unpackaged="codepkg/package.xml"/>
    </target>
        
     <!-- 定义删除自定义对象的目标 -->
    <target name="deleteCustomObject">
        <sf:deploy username="${sf.username}" password="${sf.password}" serverurl="${sf.serverurl}" maxPoll="${sf.maxPoll}" deployRoot="removecodepkg"/>
    </target>

</project>

步骤6:创建(已经存在的话就修改)对应位置的Package.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>*</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexTrigger</name>
    </types>
    <version>59.0</version>
</Package>

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <fullName>MyPkg</fullName>
    <types>
        <members>*</members>
        <name>CustomObject</name>
    </types>
        
        <types>
        <members>*</members>
        <name>StandardObject</name>
    </types>
    <version>59.0</version>
</Package>
3.4 通过Ant迁移工具(Ant Migration Tool)取代码

步骤1:先进到salesforce_ant的sample目录下
步骤2:通过[ant retrieveCode]命令取代码

3.5 通过Ant迁移工具部署代码

步骤1:先进到salesforce_ant的sample目录下
步骤2:通过[ant deployCode]命令部署代码

出现上述错误的原因是:Apex没有测试类,导致覆盖率不够。追加测试类后,部署成功,如下:

假设,只想修改&部署AccountHandler.cls这一本代码,那么,本地修改后,并只保留如下文件,执行上述命令部署即可

3.6 使用Ant迁移工具删除组件

要删除组件,请使用与部署组件相同的过程,但还要包含一个名为destructiveChanges.xml 的删除清单文件,并在此清单中列出要删除的组件

destructiveChanges.xml源文件:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <fullName>codepkg</fullName>
    <types>
        <members>SampleDeployClass</members>
        <members>SampleFailingTestClass</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>SampleAccountTrigger</members>
        <name>ApexTrigger</name>
    </types>
    <version>59.0</version>
</Package>

例如,我们要删除环境中一个自定义对象:

这时,destructiveChanges.xml的内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>AntDelObj__c</members>
        <name>CustomObject</name>
    </types>
    <version>59.0</version>
</Package>

与destructiveChanges.xml同目录下package.xml的内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <version>59.0</version>
</Package>

运行[ant deleteCustomObject]即可删除此自定义对象

还有一些其他的部署方式,如SalesforceDX、CI/CD Pipeline或者其他一些第三方工具,这里就不一一介绍了。

总结:部署方式,还是要根据项目的实际情况来进行选择,确保安全且便捷。

Copyright © 乔木船长

个人主页:乔木船长

欢迎转发点评和指正!

  • 50
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值