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

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

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

1、更改集(Change Set)

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

更改集有两种:

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

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

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

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

2.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】📂打开后是下面文件:
<?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工具(免安装)
https://ant.apache.org/bindownload.cgi

步骤3:下载Ant迁移工具(免安装)
https://developer.salesforce.com/docs/atlas.en-us.248.0.daas.meta/daas/forcemigrationtool_install.htm

注意,解压缩后,将[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>
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <Package xmlns="http://soap.sforce.com/2006/04/metadata">
 3     <fullName>MyPkg</fullName>
 4     <types>
 5         <members>*</members>
 6         <name>CustomObject</name>
 7     </types>
 8         
 9         <types>
10         <members>*</members>
11         <name>StandardObject</name>
12     </types>
13     <version>59.0</version>
14 </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源文件:
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <Package xmlns="http://soap.sforce.com/2006/04/metadata">
 3     <fullName>codepkg</fullName>
 4     <types>
 5         <members>SampleDeployClass</members>
 6         <members>SampleFailingTestClass</members>
 7         <name>ApexClass</name>
 8     </types>
 9     <types>
10         <members>SampleAccountTrigger</members>
11         <name>ApexTrigger</name>
12     </types>
13     <version>59.0</version>
14 </Package>
例如,我们要删除环境中一个自定义对象:
这时,destructiveChanges.xml的内容如下:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <Package xmlns="http://soap.sforce.com/2006/04/metadata">
3     <types>
4         <members>AntDelObj__c</members>
5         <name>CustomObject</name>
6     </types>
7     <version>59.0</version>
8 </Package>
与destructiveChanges.xml同目录下package.xml的内容如下:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <Package xmlns="http://soap.sforce.com/2006/04/metadata">
3     <version>59.0</version>
4 </Package>
运行[ant deleteCustomObject]即可删除此自定义对象

 

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

 

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

 

欢迎评论转发,如文中有问题欢迎指正!

Copyright © 乔木船长

博客主页:https://www.cnblogs.com/captainqiaomu/

posted on 2024-04-03 13:47  乔木船长  阅读(90)  评论(0编辑  收藏  举报

导航