原文:
annas-archive.org/md5/6eb8e0881caa9511876ed36f7f355527译者:飞龙
前言
随着 Salesforce 平台向更加复杂的领域发展,架构师面临着对高级解决方案日益增长的需求。成功的 Salesforce 项目的关键在于有效的 DevOps 实践,本书通过提供有关 Salesforce 组件的战略性和实用性见解,帮助你实现这一目标。
本书首先从培养 DevOps 思维方式开始,重点关注协作、协调和沟通。它帮助你学习如何高效地展示治理、可视性和问责制。在此架构基础上,你将深入了解如何利用 SFDX 的功能规划你的策略。一旦你掌握了 Salesforce 的打包机制,你将学会如何使用免费的软件构建 CI/CD 堆栈,并将其配置为自动化交付变更。接着,你将解决成熟 DevOps 流程的运营问题,探索诸如票务管理、备份、变更监控和数据播种等主题。这些都是保持 Salesforce 组织健康和整洁的关键。最后,你将了解第三方解决方案的生态系统,这些解决方案提供开箱即用的能力,加速你的 Salesforce DevOps 之旅。
在本书结束时,你将彻底弄懂 Salesforce DevOps,能够以 DevOps 专业人士的身份交付 Salesforce 项目。
本书适合谁阅读
如果你是 Salesforce 架构师或资深开发人员,想要将 DevOps 最佳实践应用到你的项目中,那么这本书适合你。为了从本书中获益,你应该对 Salesforce 平台的开发(包括代码和低代码)有深入的了解,理解元数据、JSON 和 XML 等概念,并且熟练使用命令行操作。
本书内容概览
第一章,Salesforce 变更部署简史,讨论了在 Salesforce 平台上开发的独特挑战,并回顾了过去解决这些挑战的尝试。
第二章,构建 DevOps 文化,通过强调在技术之前建立文化思维方式的必要性,为 DevOps 的成功奠定了基础。
第三章,源代码管理的价值,探讨了实现 DevOps 的基础技术——源代码管理。
第四章,测试你的变更,重申了定期和早期测试的重要性,并探讨了实现这一目标的方法。
第五章,使用 SFDX 的日常交付,通过 Salesforce 的 SFDX 工具集,讲解了一个相对典型的开发和部署场景。
第六章,探索打包,介绍了 Salesforce 中另一种变更交付方式,回顾了不同类型的 Salesforce 打包。
第七章, CI/CD 自动化,深入探讨构建完整 CI/CD 流水线的强大 DevOps 自动化技术,并为流行平台提供示例。
第八章, 工单系统,探讨了工单系统如何增强您的流程,并通过可管理的分块支持快速交付。
第九章, 数据和元数据备份,强调了备份数据和元数据的重要性,并探讨了各种备份方法。
第十章, 监控变更,讨论了跟踪整个 Salesforce 环境变更的重要性,确保没有遗漏任何变更。
第十一章, 在开发环境中进行数据播种,演示了在 Salesforce 开发生命周期中准确测试数据的需求,以帮助准确测试。
第十二章, Salesforce DevOps 工具 – Gearset,开始我们对第三方 Salesforce DevOps 平台的探索,首先看看 Gearset。
第十三章, Copado,继续探讨 Salesforce DevOps 生态系统,我们转向 Copado。
第十四章, Salesforce DevOps 工具 – Flosum,转向 Salesforce DevOps 的下一个重要参与者,概述了 Flosum。
第十五章, AutoRABIT,完成了我们对最常见的第三方 Salesforce DevOps 工具的评估,重点介绍了 AutoRABIT 的功能。
第十六章, 其他 Salesforce DevOps 工具,了解其他较不常见但仍然可选的 Salesforce DevOps 解决方案。
第十七章, 结论,总结了我们学到的内容,并重申了重要的收获。
要充分利用本书
本书的性质假定您对 Salesforce 开发有所了解,这表明您可能已以某种方式部署了变更。本书不假设您具有现有的 DevOps 知识,因为这在书中有所涵盖。
| 本书涵盖的软件/硬件 | 操作系统要求 |
|---|---|
| Salesforce | Windows,macOS 或 Linux |
| Git | |
| 其他软件或平台将根据章节逐个讨论 |
如果您使用本书的数字版,我们建议您自行输入代码或从书的 GitHub 存储库中访问代码(下一节中提供链接)。这样做将有助于避免与复制粘贴代码相关的潜在错误。
下载示例代码文件
您可以从 GitHub 上下载本书的示例代码文件,链接为github.com/PacktPublishing/Salesforce-DevOps-for-Architects。如果代码有更新,它将在 GitHub 库中更新。
我们还提供来自丰富书籍和视频目录的其他代码包,链接为github.com/PacktPublishing/。赶快去看看!
使用的约定
本书中使用了多种文本约定。
文本中的代码:表示文本中的代码单词、数据库表名、文件夹名称、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 用户名。以下是一个示例:“相关的ContactId和OpportunityId字段需要正确填写,以便关联记录。”
代码块设置如下:
from salesforce_bulk import SalesforceBulk
import csv
# Salesforce credentials
username = 'your_username'
password = 'your_password'
security_token = 'your_security_token'
当我们希望将注意力集中在代码块的特定部分时,相关的行或项会以粗体显示:
from salesforce_bulk import SalesforceBulk
import csv
# Salesforce credentials
username = 'your_username'
password = 'your_password'
security_token = 'your_security_token'
任何命令行输入或输出都如下所示:
sf force package create –n "My Managed Package" -t Managed –r force-app
粗体:表示一个新术语、一个重要的词汇,或者是你在屏幕上看到的单词。例如,菜单或对话框中的词语通常以粗体显示。以下是一个示例:“通过点击立即获取按钮在 AppExchange 列表中安装包,这将启动客户的 Salesforce 环境中的安装过程。”
提示或重要事项
显示如下。
联系我们
我们始终欢迎读者的反馈。
一般反馈:如果你对本书的任何方面有疑问,请通过电子邮件联系我们,地址是 customercare@packtpub.com,并在邮件主题中注明书名。
勘误表:尽管我们已尽力确保内容的准确性,但错误总会发生。如果您在本书中发现错误,我们将非常感谢您向我们报告。请访问www.packtpub.com/support/errata并填写表单。
盗版:如果你在互联网上发现我们作品的任何非法复制品,任何形式的都可以,如果能提供相关位置或网站名称,我们将不胜感激。请通过电子邮件联系版权@packt.com,并附上材料的链接。
如果你有兴趣成为作者:如果你在某个领域有专业知识,并且有兴趣编写或参与书籍创作,请访问authors.packtpub.com。
分享您的想法
一旦你阅读了Salesforce DevOps for Architects,我们很想听听你的想法!请点击这里直接进入本书的 Amazon 评价页面,并分享你的反馈。
您的评价对我们和技术社区都很重要,能帮助我们确保提供优质的内容。
下载本书的免费 PDF 副本
感谢您购买本书!
您是否喜欢随时随地阅读,但无法携带实体书?
你的电子书购买与选择的设备不兼容吗?
别担心,现在每本 Packt 书籍都附带免费的无 DRM 限制的 PDF 版本
随时随地,任意设备上阅读。可以搜索、复制并粘贴你最喜爱的技术书中的代码,直接应用到你的程序中
福利不仅仅如此,你还可以独享折扣、新闻通讯,并每天在邮箱中收到精彩的免费内容
按照以下简单步骤即可享受福利:
- 扫描二维码或访问以下链接
https://packt.link/free-ebook/9781837636051
packt.link/free-ebook/9781837636051
-
提交你的购买凭证
-
就这样!我们将直接把你的免费 PDF 及其他福利发送到你的邮箱
第一章:Salesforce 变更部署的简史
Salesforce 的交付模式每年发布三次主要版本,自 2000 年首次推出以来,平台经历了显著的发展。从最初作为一个主要的销售工具开始,Salesforce 已发展成一个独立的开发平台。随着这一变化,平台对自定义开发最佳实践的需求应运而生,并且需要高效地交付这些自定义功能。
本章将探讨在 Salesforce 平台上进行变更和交付的历史,以了解内置工具当前的不足之处。这将为理解 DevOps 流程的必要性提供背景,并展示现阶段的技术现状。我们将讨论以下主要内容:
-
自定义 Salesforce 的开端
-
Apex 和 Visualforce
-
沙盒和变更集
-
SFDX 和暂存组织
-
DevOps 中心
与本书的其他章节不同,本章并不一定提供可操作的步骤或最佳实践指南,供您在 Salesforce 实施中应用。然而,成为一名优秀 Salesforce 架构师的基本原则之一就是理解我们决策背后的 原因。通过回顾 Salesforce 作为开发平台的发展历史,以及它如何不断朝着现代软件开发方法和工具迈进,我们能更好地理解在 Salesforce 生态系统中实施 DevOps 的必要性。
Salesforce 作为开发平台的历史介绍
对于任何足够复杂的 IT 系统,在实施阶段和日常运营中,考虑全面的架构因素都至关重要。这些考虑不仅仅是技术层面的内容,还包括业务层面的因素——强有力的治理、准确且及时更新的文档、可定义的指标,以及能够向企业展示的投资回报。
随着 Salesforce 的发展,应用这些架构因素的需求也随之增加。Salesforce 在许多组织中已经成为 一等公民,作为企业运作的数字枢纽。因此,一个适当的变更管理过程对于避免服务中断至关重要,而 DevOps 是满足这一要求的完美方法。DevOps 承诺更快、更准确的软件发布、更少的错误、更少的停机时间以及在问题发生时更快的恢复路径。
我们可以合理地将 2003 年视为 Salesforce 成为开发平台的起点。在公司首届 Dreamforce 大会——这一至今每年仍持续举办的旗舰会议上,他们宣布了客户如何自定义平台的根本性变化。这个被称为 sforce 2.0 的版本,最初被定位为 按需应用服务器,并包含一些关键功能,我们将接下来详细探讨。
自定义对象
此时引入的第一个重大创新是能够创建额外的自定义对象,类似于数据库表,用来补充 Salesforce 为其核心 CRM 功能提供的内置对象。这些自定义对象本身可以包含自定义字段,并共同为在平台上开发自定义业务应用提供了早期框架。
突然,Salesforce 不再仅仅是一个销售 CRM 系统,而是开始向成为一个开发自定义业务应用的平台转型。Salesforce 团队现在可以开始根据他们业务的核心需求定制流程和应用,无论他们所属的行业是什么。例如,一些 Salesforce 客户将利用这一能力来构建处理业务支持案例的能力——这项功能直到 2009 年 Service Cloud 发布时才成为平台的核心能力。
S-Controls
S-Controls(最初称为 sforce controls)是新定制功能中两个编程元素之一。S-Controls 将功能和用户界面元素结合在一个容器中,可以包含任何可以在浏览器中显示的项目,例如 Java 小程序、ActiveX 控件和网页表单。
尽管 S-Controls 已经被弃用很久,但它们是开发者首次可以用编程方式定制平台的工具,它们使开发者能够将其他非 Salesforce 开发的技能和编程语言带入平台。它们使 Salesforce 开发者能够利用 HTML 和 JavaScript 创建自定义页面和用户界面组件。从这个角度来看,它们可以被视为 Lightning Web Components 的早期先驱,尽管当时并没有我们今天使用的最佳实践。
SOQL
Sforce 2.0 还引入了 Sforce 对象查询语言 (SOQL),它提供了一种从标准对象和自定义对象中查询数据的方式,语法类似于行业标准的 SQL。这为开发者提供了一个强大的机制,能够通过编程查询 Salesforce 组织中的数据,并对查询结果进行操作。
如果从架构师的角度看 SOQL,我们可以看到它如何与确保数据质量与元数据质量同等重要的需求相一致。干净、可操作的数据是推动业务决策的关键交付物之一,应始终是架构师的重要任务之一。SOQL 提供了一种额外的方式来处理这些数据,无论是日常业务中的操作数据,还是作为从平台中提取数据进行归档的手段。我们稍后将探讨这一后者的使用案例,特别是在分析良好架构的 Salesforce DevOps 策略中备份的重要性时。
Sforce Web 服务
sforce 2.0 的另一个基本新功能是能够将 Salesforce 与其他平台集成,这得益于通过 Web 服务 API 曝露了对象模型和业务逻辑。使用当时的标准 SOAP 和 WSDL,现在可以通过网络从更传统的开发环境和系统与 Salesforce 组织进行交互。
工作流
sforce 2.0 引入的最后一个重大元素是一个名为工作流的业务过程自动化引擎。通过定义响应数据变化的工作流规则,可以触发业务逻辑,处理诸如升级、通知和根据事件自动更新数据等操作。工作流仍然是一个配置而非代码的功能实现方式,但正如我们稍后看到的,作为一种低代码解决方案,并不意味着在 DevOps 中应该被忽视。
Apex 和 Visualforce
在 2006 年的 Dreamforce 大会——Salesforce 的旗舰会议上,联合创始人 Parker Harris 揭示了迄今为止 Salesforce 平台最重要的变化。客户现在可以使用 Salesforce 自己的编程语言——Apex,直接在 Salesforce 内部开发自定义解决方案。
作为流行的 Java 编程语言的变体,Apex 首次通过代码实现自动化。最初仅限于触发器,开发者现在可以通过编程方式响应数据变化。
在平台演变的后期,Apex 引入了更多面向对象的范式,随着 Apex 类的到来,允许开发者构建比仅使用触发器更结构化、解耦的实现方式。
除了 Apex,Salesforce 平台的另一项重大创新是 Visualforce,后者于 2008 年推出。Visualforce 从当时的其他 UI 语言,如 ASP 或 PHP 中汲取灵感,将 HTML 与编程元素和标记结合在一起,这些标记又连接回你在 Apex 中编写的逻辑。Visualforce 很快取代了之前推出的 S-Controls,成为在 Salesforce 实现中编写自定义用户界面和页面的标准方式。
随着平台在开发和定制方面的所有这些进展,Salesforce 随后将注意力转向了如何交付这些功能。让我们在下一节中看看这些功能最初是如何被引入的。
沙箱和变更集
随着 Salesforce 的不断成熟,需要能够在生产环境外安全地进行更改,并在准备好时将其迁移到生产环境的需求变得愈加明显。然而,DevOps 创新的步伐似乎未能跟上 Salesforce 作为开发平台崛起的步伐。
沙盒功能在 2006 年冬季发布时推出,使客户能够在远离生产环境的安全环境中尝试更改和增强功能——但也有一个限制。沙盒的原始实现并不允许你将这些更改回传到生产环境,这意味着你必须手动重新创建这些更改到生产环境中。这将既耗时又容易出错。
为了应对这一不足,变更集最初在 2010 年冬季发布的 beta 版本中推出,距沙盒发布已有约四年,最终它们在 2011 年春季发布中成为了正式版本。变更集最终允许在沙盒环境中进行的代码和配置工作打包并在环境之间迁移,无论是从沙盒到沙盒,沙盒到生产,还是生产到沙盒。这为将 Salesforce 环境作为成熟应用程序开发生命周期的一部分进行规划开辟了新可能——现在,你可以在生产上线前拥有开发、QA、UAT 和预发布环境。这是迈向与其他开发平台相匹配的 DevOps 过程的第一步。
元数据和工具 API
为了为开发和部署提供更好的工具,Salesforce 在 2008 年春季发布了两个重要的 API——元数据 API 和 2013 年春季发布的工具 API。尽管它们都履行了相似的功能,但它们的目标和功能上有一些重要的区别。
元数据 API
在最简单的层面上,元数据是描述你数据结构的数据,但对于 Salesforce 平台来说,这有些过于简化。元数据一词还涵盖了 Salesforce 的许多配置和自定义元素——截至写作时,Salesforce 自己的元数据覆盖报告可在 developer.salesforce.com/docs/metadata-coverage 查阅,报告显示平台上有 601 种元数据类型,其中绝大多数都在元数据 API 中得到支持。
元数据 API 可以用来在环境之间移动这些元数据。你可以从一个 Salesforce 组织中检索元数据作为 XML 文件,并将其部署到另一个组织中。就像变更集一样,这些操作的源和目标可以是沙盒、生产环境,或者正如我们稍后会学习的那样,临时组织。
此外,元数据 API 允许你在 Salesforce 组织中创建、更新和删除元数据,这为 Salesforce 开发和在平台上采用 DevOps 方法解锁了一个基本能力。
平台上的大多数 DevOps 工具都依赖于元数据 API,无论是 Salesforce 自家的 SFDX、新的 DevOps 中心,还是各种可用的第三方 Salesforce DevOps 解决方案。它们都利用元数据 API 来协调代码和配置在不同环境之间的迁移。
工具 API
虽然 Metadata API 大部分处理了元数据管理的繁重工作,Salesforce 推出了 Tooling API,提供了更多功能,更好地对接了 DevOps 实践,比如更小更精确的元数据检索和部署,运行单元测试并查看测试结果及相关代码覆盖率,以及支持一些额外的代码调试能力。
能够管理单元测试周期使 Tooling API 成为在 DevOps 过程和工具中另一个强有力的选择。作为架构师,我们需要确保我们不仅能够快速交付代码,而且代码质量符合要求——它不会在孤立环境中出现问题,不会破坏现有代码,并且能够在 Salesforce 组织之间无缝部署。这些都是变更失败率的因素,是我们在下一章中将要探讨的基本 DevOps 指标之一,因为我们将研究作为架构师开发 DevOps 文化的关键考虑因素。
Tooling API 主要面向希望为平台创建额外开发工具或应用程序的人群,并且其到来预示着 Salesforce 开发支持在当时流行的 IDE 中,我们将在接下来看到。
Force.com IDE 和 Mavensmate
使用了利用元数据和工具 API 的新工具,不再需要在 Salesforce 平台内部开发。为了帮助开发人员采用这种方法,Salesforce 开始研究如何提供符合当时标准的标准化开发人员体验。让我们来看看当时可用的工具。
Force.com IDE
早期利用这一特性的 IDE 之一就是 Salesforce 自己的 Force.com IDE。
基于流行的 Eclipse 开发环境的模块化插件架构构建,Force.com IDE 利用新的 API 允许开发人员不仅使用适当的编辑器编码,还可以直接从 IDE 将更改保存回他们的开发组织,而无需切换回 Salesforce 用户界面。
Force.com IDE 很快变得非常流行,因为它是为 Salesforce 开发人员提供现代环境的首次尝试,并具备其他平台(如 Java 或 .NET)开发人员期望的一些便利条件。然而,它同样迅速地因为速度慢和不稳定而声名狼藉。
Mavensmate
作为 Eclipse 和插件的重量级安装的解毒剂,并作为提高速度和稳定性的潜在手段,2013 年见证了另一款 Salesforce 开发工具的到来——Mavensmate。
Mavensmate 采用了与 Force.com IDE 相同的插件方式,它有效地扩展了另一款编辑器Sublime Text(后来还添加了对竞争对手 Atom 编辑器的支持),但无论是底层的编辑器还是上层的 Mavensmate 插件,都要轻量得多。这使得使用 Salesforce 进行开发更加简单、快速和稳定,Mavensmate 因其速度和易用性成为了全球 Salesforce 开发者的首选——不仅仅是用于开发,还可以通过使用 Metadata 和 Tooling API 进行变更部署。
引入 SFDX
Salesforce 的变更管理状态在多年间大致保持稳定。对于大多数 Salesforce 开发者和管理员来说,变更集仍然是将更改从沙箱环境部署到生产环境的最终方式。
所有这一切在 2018 年 Salesforce 发布其 SFDX 工具链时发生了变化。SFDX 承诺带来了现代化的开发和部署实践,这些实践在其他平台上已有实现,并通过命令行工具提供。突然之间,存在了高级可脚本化部署、更强大的 IDE 集成以及管理变更的新方式的潜力。最重要的是,它标志着 Salesforce 朝着源代码驱动的开发模式转变,而不是传统的基于组织的模式。
SFDX 的命令行界面(CLI)与 scratch orgs 的引入紧密结合。这些是临时的开发环境,可以轻松地从 SFDX 创建和销毁,使用不同的配置(或组织形态)创建,并填充测试数据。从命令创建 scratch org 的能力为自动化测试开辟了新纪元,正如我们稍后将看到的那样,但它也强调了一个原则:现在,组织已不再是首要的,源代码才是核心。如果一个 scratch org 过期了,这并不是一个大问题,因为可以轻松地从源代码重新创建一个。
最终,Salesforce 意识到与开发工具紧密集成的必要性,并为流行的Visual Studio(VS)Code 环境提供了扩展,使得在 Salesforce 平台上的开发和部署变得更加简便,直接从 IDE 中操作。此外,通过构建基于开放标准的Open Command Line Interface Framework(OCLIF),它使工具能够通过插件进行扩展,这些插件来自 Salesforce 内部和外部,扩展了 SFDX CLI 的功能,填补了该工具本身无法覆盖的一些空白。
SFDX 继续是 Salesforce 推荐的开发者使用平台的方式,特别是在将其集成到 CI/CD 流水线和其他自动化工具中。截止到 2022 年 12 月,Salesforce 正在推动统一命令行界面的发展,将 SFDX 命令行和更新的 SF 命令行结合起来,后者引入了更新的结构和更简洁的方法。这一整合有望带来一个更高效的命令行工具集,提升构建强大 DevOps 流水线的便利性。
DevOps 中心
Salesforce 长期以来一直承认平台已经超出了变更集的局限,但 SFDX(至今依然如此)在客户眼中被视为仅供开发人员和那些熟悉命令行的用户使用的工具,尽管 VS Code 扩展让它变得更易于使用。一个由第三方提供商如 Gearset、Copado、AutoRABIT 和 Flosum 等组成的庞大生态系统已崛起,为提供符合更广泛 IT 行业最佳实践的强大 DevOps 平台提供支持。这些工具为 Salesforce 开发人员和管理员提供了诸如组织间比较、版本控制、静态代码分析和部署流水线等功能。
Salesforce 通过发布 DevOps 中心进入了这一领域,该产品在 2022 年 12 月正式发布。虽然它的功能不如第三方生态系统中的现有解决方案丰富,但它代表了 Salesforce 对所有用户信息传递的变化——从变更集部署转向更易于操作的方式,无论你是低代码还是专业代码的管理员或开发人员。
我们将在后面的章节中深入探讨 DevOps 中心的具体内容(以及第三方 Salesforce DevOps 领域的领先解决方案),但重要的是要看到这个新产品在思维方式上的根本转变,特别是当它放在上述平台变更创建和交付历史的背景下来看。
DevOps 中心将 Salesforce DevOps 中经过多年逐步建立的最佳实践集中整合,并通过平台内易于理解的本地界面呈现:
-
它引导 Salesforce 从业人员向一种模型转变,在该模型中,源代码管理是变更的真实版本,而不是沙箱组织。
-
它鼓励通过工作项或用户故事来实现孤立的、增量的变更——这一概念是敏捷运动推广的,并且在许多其他平台和组织的 DevOps 策略中广泛应用。
-
最重要的是,它为变更交付提供了更好的可见性和问责制
这些是 DevOps 流程总体架构的因素,稍后在本书中我们将深入探讨。它并没有在初始版本中全面覆盖每个方面,应该被视为一个 DevOps 工具,而不是一个 DevOps 解决方案,但作为一种教育 Salesforce 用户了解 DevOps 基础并帮助他们逐步摆脱变更集的方式,它是一个非常坚实的起点。
摘要
在本章中,我们回顾了 Salesforce 作为开发平台的发展历史,并了解了多年来如何添加新功能。我们还探讨了如何在 Salesforce 上交付这些更改的方式,从变更集到使用它们的各种 API 和工具,再到 DevOps Center 的出现。
拥有这些知识后,我们不仅能够更好地理解平台的发展历程,还能理解一些设计选择背后的理由,了解一些较旧的实现方式,这在需要处理旧版 Salesforce 组织时常常会非常有用。
作为架构师,重要的是不要把 DevOps 工具当作理所当然,能够使用各种不同的方式和解决方案,不管它们有多古老,都将帮助我们改进 Salesforce DevOps 的现状,以便更好地交付我们的实施方案。在接下来的章节中,我们将讨论一些最新的工具,更重要的是,讨论塑造现代 Salesforce DevOps 的技术和流程。
第二章:构建 DevOps 文化
成功实施 DevOps 的核心不在于使用的技术和工具。相反,建立并与新工作方式保持一致的团队文化是 DevOps 的最关键因素。
在本章中,我们将讨论 DevOps 的线下方面的重要性,以及协作和沟通文化如何是 DevOps 成功的基础。我们将探讨在组织中推动采纳和与最佳实践保持一致的方法。过程中,我们将探索以下内容:
-
为什么文化是 DevOps 转型的关键,以及我们如何开始构建它
-
努力推动强有力的沟通以促进协作
-
推动采纳 DevOps 方法并与其保持一致的方式
需要建立 DevOps 文化
软件开发及交付的历史悠久且不断变化。随着技术领域的变革,企业对将这些技术交到客户手中的需求也在不断增加。DevOps 代表着根据这一需求进行交付的推动力,它取代了传统的单体软件发布、漫长的项目周期和不透明的瀑布式开发方法。
当我们把 DevOps 视为一种变革交付方式时,很容易首先关注软件工具,但这不应该是你 DevOps 之旅的起点。同样重要的是要牢记,任何 DevOps 转型都不应该是具有指导性的;它应该与你和你所在组织的工作方式保持一致。对于那些曾经在其他团队或系统中有过 DevOps 经验的人来说,这一点尤为重要——DevOps 没有“万能”的方法,虽然经验可以帮助在新团队中建立 DevOps 文化,但你应该注意根据团队的特点进行定制。
然而,成功的 DevOps 团队有一些共同的特征,这些特征对高效的团队始终有效。因此,你应该考虑将这些特征纳入你的计划中,以将 DevOps 文化付诸实践。让我们先来看看成功的 DevOps 团队的特征及其采纳的 DevOps 文化要素,然后再深入探讨如何实现它们。
明确的团队定义
顾名思义,DevOps 团队是 IT 开发团队和 IT 运维团队的结合体,但现实情况并不像表面那么简单。成功的 DevOps 团队由软件交付全流程的各个团队组成,从业务分析师收集需求和架构师设计解决方案,到开发人员实现这些解决方案,再到运维人员在 Salesforce 环境中交付这些需求。
正是在这种跨职能团队结构中,你需要为 DevOps 建立强有力的支持。一个不理解或不重视过程价值的团队,不太可能采纳 DevOps——而且只需要几次偷工减料或不按流程发布,就能破坏你们 DevOps 团队的良好工作。至关重要的是,整个团队要与 DevOps 的工作方式保持一致并参与其中,才能让这一举措取得成功。
与 DevOps 实践对齐的团队对整个应用生命周期负责,从规划到部署和维护,减少了在修复 bug 或测试失败时的对立和推卸责任。此外,DevOps 鼓励产品团队更加参与开发过程,确保他们的意见和专业知识在整个应用生命周期中得到考虑。
作为架构师,我们需要传达 DevOps 带来的价值,因为对大多数团队来说——无论是技术团队还是业务团队——这通常是让人们加入的关键因素。通过展示 DevOps 如何在我们概述的开发旅程中使每个人受益,相比于强制执行流程,我们更有可能让团队接受 DevOps。
尚未采用 DevOps 文化进行软件交付的公司,可能已经失去了对交付团队的信任,试图通过引入重型流程来防止未来失败的风险。采用 DevOps 文化的一部分就是通过提供能够帮助团队成功的工具和流程来恢复信任,并让任何失败保持在较小的范围内,而不是通过避免失败完全来拖慢一切进展。
一般来说,DevOps 和敏捷的一个好处是能够安全地迈出小步伐。DevOps 和敏捷方法提倡小步、增量发布,而非大型的、单一的部署。这种方法可以让团队更快地识别并解决问题,降低灾难性失败的风险。它还使团队能更有效地应对不断变化的需求或市场条件。因此,团队在交付准确结果和适应变化方面的信任度会增加。
紧密合作
与强大的团队并行的是彼此协作和沟通的需求。这看起来是所有工作团队中的显而易见需求,不仅仅是 DevOps 团队,但在 DevOps 中,清晰、可见性和合作的原则真正突显出来,对于其顺利运行至关重要。
为了打破软件交付的孤岛式做法并朝着共同目标努力,整个团队需要了解项目是如何交付的。像敏捷(Agile)这样的技术和像 Jira 或 Asana 这样的工具无疑会有所帮助,但这只是协作图景的一部分,正如我们稍后会探讨的那样。
持续演进
无论 DevOps 团队多么成熟,表现最好的团队总是愿意接受变化和改进。通过不断的测量、改进和重新测量,这些团队能够找出可以提高性能和准确性的领域,并加以解决。它们通常关注的最常见指标基于 DORA 指标,具体如下:
-
部署频率:团队向生产环境发布的频率
-
变更交付时间:特定功能到达生产环境所需的时间
-
变更失败率:部署失败或在生产中引起错误的部署比例
-
恢复平均时间:从生产错误或其他问题中恢复所需的时间
在 Salesforce 的背景下,衡量这些指标可能稍有不同,因为它是一个基于云的平台,具有特定的功能和限制。像部署频率、变更交付时间和恢复平均时间这样的指标很容易确定,特别是如果你有像 Jira 或 Asana 这样的工单系统来管理新工作。
变更失败率可能稍微复杂一些,因为它涉及跟踪失败的部署以及与这些部署相关的事件或缺陷数量。你可以用几种方法来处理这个问题——我们将在后续章节中讨论 Salesforce 特定的 DevOps 解决方案和平台,但作为一个使用平台内特性的示例,你可以尝试以下方法:
-
使用 Salesforce 的部署历史,可以在 部署状态 页面上查看部署的成功率和失败率。识别失败的部署及导致失败的具体组件。
-
记录所有生产事件,包括由最近部署引起的事件。你可以使用 Salesforce Case 对象来记录和跟踪事件。
-
对于每一个失败的部署或生产事件,分析根本原因并确定是否与最近的变化有关。你可以使用 Salesforce Developer Console、调试日志和测试结果来找出问题的根本原因。
-
将失败的变更数量(导致事件或缺陷的部署)除以特定期间内所做变更的总数。将结果乘以 100 得到变更失败率的百分比。
DORA 指标的起源
DORA 指标来自一个名为 DevOps Research and Assessment 的小组,该小组由 Nicole Forsgren、Gene Kim 和 Jez Humble 于 2015 年创立(并在 2018 年被 Google 收购),旨在更好地理解哪些因素导致高效能的 DevOps 团队。自从最初的研究以来,这四个指标已成为衡量 DevOps 成功的行业标准。
现在我们已经确定了强大 DevOps 文化的需求和要素,让我们更详细地看看一些创建这种文化的技巧。
协作与沟通
在理想的 DevOps 团队中,整个团队以相同的方式工作,朝着相同的目标努力——应对变更交付的成功共同承担责任。这个协作方法的核心是强有力的沟通,这种沟通可以采取多种形式,从治理整体变更管理流程所需的更正式的方式,到日常互动,这些互动构成了你常规工作流程的一部分。
沟通应该清晰、信息丰富,并且贯穿于交付生命周期的每个步骤。例如,在使用版本控制时,团队应努力始终提供有意义的提交信息和同行评审的评论。这些有助于团队以背景为基础进行下一步变更交付过程,而不仅仅是具体的变更内容。通常需要在提供足够详细的信息和相关信息之间取得平衡,你应该不断调整这种细节层次,以找到适合你和团队的最佳平衡点。
尽管本书并未深入探讨敏捷原则,但成功的 DevOps 团队与敏捷实践者之间确实存在着强烈的关联,因为这两个领域都强调定期、清晰和简洁的沟通原则,以推动项目向前发展。这些技巧涵盖了所有参与变更交付的团队成员,以确保每个人都了解并意识到工作流程和进度。
同样,工具将帮助提高日常工作的可见性和清晰度。用于管理特性通过 DevOps 流程的软件,如 Jira、Asana、Azure DevOps 等,在正确使用时可以为你的流程提供概览,并且它们与大多数 DevOps 工具以某种方式集成,以完善整个画面。许多团队已经开始摒弃电子邮件作为内部沟通媒介,而是更倾向于使用即时消息平台,如 Slack 或 Teams,作为进一步打破孤岛并消除跨职能团队之间障碍的方式。
适应远程工作的必要性导致了对数字沟通工具的依赖增加,并且在许多方面改变了团队互动的动态。由于团队成员分布在不同地点和时区,拥有能够实现实时协作的工具是至关重要的,这些工具提供即时沟通、文件共享以及与其他工具的集成。在远程工作中,并非总是能够在同一时间召集所有人进行讨论。异步沟通工具,如项目管理平台、共享文档以及消息应用中的线程讨论,使团队成员能够在方便的时候做出贡献,并让每个人了解进展。
在向远程工作转变的过程中,每个需要适应的变化都需要保持平衡。随着数字通信的普及,远程工作者可能会面临大量的消息和通知涌入。消息平台通过提供频道、线程和打盹选项等功能进行适应,帮助团队成员有效地优先处理和管理通讯。然而,保持团队成员之间的连接和参与感同样重要。消息平台促进了非正式的互动,如虚拟水冷器聊天、快速签到和社交活动,帮助团队保持联系并促进积极的团队文化。
远程工作使得团队必须在没有面对面交流所提供的背景下有效沟通。现代的远程团队沟通方法鼓励团队成员在沟通时更加简洁和清晰,同时在回应时也更加有意识。
最后,由于远程工作依赖于数字通信工具,确保数据安全性和符合行业规定变得至关重要。技术解决方案已经通过提供端到端加密、数据存储选项和针对不同行业的合规功能来做出响应。
采纳与对齐
正如我们所见,DevOps 文化的采纳应该先于 DevOps 技术的采纳。然而,在每个方面,最佳的做法始终是慢慢开始——人们常说 DevOps 是一段旅程,而不是一个目的地,为此,我们应该从一些规划开始。
开始时的问题
开始任何旅程的最佳方式是先看看我们想要去哪里,并提出一些问题:
- 预期的流程是 什么样的?
了解你的目标场景有助于集中精力,避免对业务造成不必要的干扰。例如,最终目标是能够更快地、逐步地交付业务需求,还是想采用更有计划的、基于冲刺的方式,但又能更好地看到并控制冲刺中的各个元素?事先明确目标有助于团队专注于实现这些目标。
- 新流程的目标受众是 谁?
一个新的 DevOps 过程将影响的不仅仅是开发和运维团队。如果你真的想要采纳端到端的 Salesforce DevOps 方法,你不仅需要对齐技术团队,还需要协调那些参与任务收集和分配、项目管理、发布管理、整体架构、业务审批等工作的人员。我们稍后将讨论一些治理方面的内容。
- 我们需要在当前的方法中 做出哪些改变?
虽然并非没有先例,但要完全替换现有流程的情况是比较罕见的。先评估一下你当前的交付模式,并记录下哪些有效,哪些无效。哪些瓶颈在拖慢你的进度?交付一个生产版本需要多少次尝试?如果我们重新审视之前讨论过的 DORA 指标,我们的起点在哪里?在开始 DevOps 转型之前,设定一组基准指标是衡量进展和改进的坚实方式——最终,它将帮助你衡量投资回报率,尤其在你开始采用 Salesforce DevOps 时。此外,能够向高层管理者展示问题(以及后来所做的改进)是赢得他们支持 DevOps 转型项目的无价之宝。
当这些问题摆在眼前时,开始识别采用 Salesforce DevOps 带来的潜在收益就变得更加容易,进而有助于推动团队与变化的一致性。这一步是至关重要的——所有参与者都需要成为 DevOps 转型的利益相关者,而实现这一目标的最佳方式是从两个角度来审视问题:
- DevOps 会带来哪些好处?
在确定了会直接受到 DevOps 交付模式影响的团队之后,着手向他们传达这种变化的好处。变更的可见性、更易管理的小规模工作单元、更快速的交付、稳健的测试、可预测的发布周期——这些对于 Salesforce 团队来说都至关重要,而让他们的工作变得更轻松这一总体原则,是促使他们支持变革的重要动力。
- 不采纳 DevOps 的风险是什么?
同样,评估停滞不前、什么都不改变的风险也是非常重要的。如果你不采用更快速、更灵活的交付模式,你有可能会被更敏捷的竞争对手超越。如果你不实施一个强大的备份和恢复策略,你可能会失去你宝贵的业务数据或客户数据。如果你坚持使用更传统的交付模式,这些模式可能既冗长又繁琐,你可能会面临团队的不满和倦怠,最终导致他们离开。
让团队的工作更轻松
如果你的 Salesforce 团队对 DevOps 概念、技术,甚至术语都不熟悉,那么他们可能会觉得转向新的交付模式是一个令人生畏的前景。然而,像所有大型项目一样,最优的方式通常是从小的环节开始,慢慢推进,逐步扩展和迭代。
例如,由于源代码管理的概念历来是开发人员专属的领域,许多 Salesforce 管理员对这种方法并不熟悉。仅仅这一领域就是一个很好的起点——即使您不一定直接进入源代码管理的应用,单是让管理员和开发人员对齐工作方式,便有助于在建立 DevOps 文化的过程中促进沟通与协作。
让管理员和开发人员以这种方式更紧密地合作,也有助于采用另一套促进 DevOps 文化的有效技术。高效能的 Salesforce DevOps 团队经常利用辅导和指导,不仅提升团队的整体技能和信心,而且作为协作工作的助力,打破孤岛,形成多学科的 DevOps 团队。
当然,这不仅仅是关于流程,您还应确保您的团队拥有必要的工具,以帮助顺利推进 DevOps 之旅。作为架构师,您应时刻关注 Salesforce DevOps 的生态,评估各种组件,例如版本控制提供者、新工具或现有工具的更新,甚至是完整的 Salesforce DevOps 平台——其中一些我们将在后续章节中讨论。
治理与风险管理
DevOps 文化应时刻关注管理和减轻业务风险的需求,并应有强大的治理框架来提供保障。重要的是要认识到,虽然 DevOps 解锁了快速交付变更的潜力,但它并非没有控制的自由放任。
我们的 DevOps 过程的治理应该与您的业务,或您的客户的业务运营所采用的治理相一致。如果没有正确的流程,您有可能失去在开始 DevOps 旅程时所促成的对齐和采用的价值。您有可能重新回到使用冗长、单体发布的模式,而不满的客户正在等待那些深埋在待办事项中的变更。您还可能面临低质量变更的风险,最坏的情况是,这可能会损害您的系统、数据和声誉。
金融服务和医疗等受监管行业在软件开发和部署方面面临独特的挑战。这些行业受到广泛的法规、标准和合规要求的约束,这些法规规定了软件开发、测试和部署的方式。这些法规旨在保护敏感数据、确保数据隐私,并防止欺诈和其他犯罪活动。
在金融服务行业,像萨班斯-奥克斯利法案、支付卡行业数据安全标准(PCI DSS)和反洗钱(AML)等法规要求金融机构在软件开发、测试和部署过程中实施强有力的控制。同样,在医疗保健行业,像健康保险流通与问责法案(HIPAA)和通用数据保护条例(GDPR)等法规要求医疗机构保护患者数据并确保数据隐私。DevOps 可以通过为软件开发提供结构化过程,包括自动化测试、安全扫描和持续监控,帮助这些行业的组织遵守相关法规。这可以确保软件在开发时考虑到安全性和隐私,并且在软件部署之前识别并解决任何潜在的安全漏洞。
一个好的治理框架通过在整个生命周期中实施必要的制衡措施来解决这些问题。从优先排序工作和决定推进哪些项目,到技术设计和实施考虑,治理使各方利益相关者能够为成功提供反馈。
这一方法的核心是卓越中心(CoE),它负责监督这一过程。它指导和通知与 Salesforce 相关的业务目标、交付方法和使用的技术。它还负责与组织内部的利益相关者和最终用户沟通,识别和管理项目的业务风险,并确保项目能够交付价值。
因此,CoE 通常包含或与具有特定职责的不同小组合作。例如,变更管理小组将负责批准进入 Salesforce 的变更,并确保变更质量合适,且在允许其发布到生产环境之前已进行充分的测试。这通常通过定义所需的流程和行为来确保交付质量,而不是由变更管理小组直接执行测试,测试仍将是技术团队的责任。
然而,在变更管理小组方面,应该注意一些问题。在 Nicole Forsgren、Jez Humble 和 Gene Kim 合著的《加速:精益软件与 DevOps 的科学:构建和扩展高效能技术组织》一书中,作者强调了快速反馈回路、持续实验以及学习和改进文化的重要性——这些因素表明,传统的变更管理实践可能并不总是与高效能 DevOps 团队的需求对接。
另一方面,指导委员会是一个由业务主导的团队,确保变更始终与业务战略、愿景和价值观保持一致。在所有这些领域中,应该有一位执行赞助人,能够并且有权做出决策并解锁业务瓶颈。
向领导层阐明 CoE 的必要性
希望向组织或客户的领导层提出建立 CoE 案例的架构师,通常会借鉴展示任何提案给利益相关者时的相同技巧。然而,某些具体元素应被视为该提案的基本组成部分。以下是一些典型的关注领域:
| 主题 | 详情 |
|---|---|
| 定义目标和宗旨 | 阐明 CoE 的目标,如推动持续改进、分享最佳实践、促进协作以及加速 DevOps 在组织中的采用。 |
| 建立商业案例 | 创建一个有说服力的商业案例,展示 CoE 的好处,包括潜在的成本节省、提高的运营效率、更快的市场时间和更高的客户满意度。展示行业示例和相关的成功故事。 |
| 确定关键利益相关者 | 确定并与关键利益相关者互动,如高层管理、开发和运维团队。将他们纳入决策过程,并在随后的 CoE 建立过程中发挥作用。 |
| 提出 CoE 结构 | 提出 CoE 的结构,包括角色、职责和汇报关系。估算设立和维持 CoE 所需的预算和资源。职位可能包括 DevOps 教练、产品负责人和持续改进专家。 |
| 制定路线图 | 制定 CoE 实施的路线图,包括里程碑、时间表和关键绩效指标(KPIs)。为领导层提供一个清晰的计划,以便跟踪和监控进展。 |
| 变更管理计划 | 认识到实施 CoE 可能涉及重大文化和组织变革。提出一项变更管理策略,以应对潜在的抗拒、沟通和培训需求。 |
| 促进协作 | 强调跨职能协作和知识共享的重要性。提出促进沟通和协作的工具和平台,如聊天平台、维基或视频会议系统。 |
| 启动试点并迭代 | 提议从一个试点项目开始,涉及一个或多个团队来测试和完善 CoE 方法。让组织从试点中学习,进行调整,并在更广泛的 DevOps 采用过程中逐步扩展 CoE。 |
| 定期报告进展 | 确保将 CoE 的进展定期报告给领导层,包括成功、挑战和收获。通过透明化保持高层管理的支持和承诺。 |
| 展示持续价值 | 持续突出 CoE 对组织的积极影响,包括效率、质量和创新方面的可量化改进。维护并扩大对 CoE 的支持,以及其在更广泛 DevOps 采用中的角色。 |
表 2.1 – 提案中需要考虑的要素
克服抗拒和犹豫
有几个常见的原因,可能导致人们最初抗拒在他们的组织中实施 DevOps,认为“这听起来不错,但在这里做不到。”让我们解决其中的一些原因,并提供反驳,帮助消除这些担忧:
| 领域 | 抗拒 | 反驳 |
|---|---|---|
| 组织结构和文化 | 现有的组织结构和文化促进了团队之间的隔阂,并不鼓励协作 | DevOps 是打破隔阂并促进协作的机会。从小的变化开始,例如创建跨职能团队,并随着组织适应新方法逐步扩大 DevOps 措施。 |
| 技能和专业知识缺乏 | 团队成员缺乏实施 DevOps 实践和工具的技能和知识 | 投资培训和提升团队成员技能,并考虑聘请或与专家合作,帮助指导 DevOps 转型。持续学习是 DevOps 的核心原则,因此发展这些技能应该被视为一个持续的过程。 |
| 资源和预算有限 | 没有预算或资源投资于新工具、技术和 DevOps 转型所需的培训 | DevOps 可以帮助提高效率,并在长期内降低成本。从利用现有工具和资源开始,随着投资回报率的展示和组织的认可,逐步扩大 DevOps 能力。 |
| 害怕失败和干扰 | 改变现有的流程可能导致干扰,并对当前项目产生负面影响 | DevOps 关注持续改进和从失败中学习。从小而低风险的项目开始,以最小化潜在干扰,并利用学到的经验在处理更大项目之前精炼方法。 |
| 遗留系统和技术债务 | 现有的基础设施和遗留系统使得采用现代 DevOps 实践和工具变得困难 | DevOps 可以通过促进渐进式改进和培养创新文化来帮助解决技术债务和现代化遗留系统。优先处理基础设施中最关键的部分,并制定引入 DevOps 实践的路线图。 |
| 缺乏管理支持 | 管理层没有看到 DevOps 的价值,或不愿意投资必要的变革 | 通过强调 DevOps 的潜在收益,建立一个强有力的商业案例。分享其他组织的成功故事和最佳实践,并考虑开展试点项目,亲自展示 DevOps 的价值。 |
| 法规和合规问题 | 采纳 DevOps 实践可能与在高度监管行业中的合规要求冲突 | DevOps 可以通过自动化流程、确保一致性和提供更好的可见性来改善合规性。与合规和安全团队合作,确保你的 DevOps 实践符合行业法规和组织政策。 |
表 2.2 – 驳斥顾虑的理由和反驳
通过解决这些常见问题并展示采纳 DevOps 的潜在好处,你可以帮助克服阻力,鼓励利益相关者接受这一变革性方法。
总结
有一句话常被引用(有时甚至被误引用):“文化吃掉战略早餐”,这句话在 DevOps 的世界里尤其贴切。无论你制定的 DevOps 采纳战略有多么精妙,如果你的团队没有接受所需的文化和心态,它也不会成功。通过推广 DevOps 流程的优势,确保整个团队一起协作,并在过程中保持强有力的沟通,你为成功的 Salesforce DevOps 转型奠定了基础,并可以在此基础上,结合我们在本书下一部分将探讨的工具和技术继续发展。在接下来的两章中,我们将首先看一下测试在 DevOps 生命周期中的重要作用,然后再看一个考虑到这些因素的典型 SFDX 和 Git 工作流示例。
文化吃掉战略早餐——或者说,它真的是这样吗?
这句话通常归功于著名的管理专家彼得·德鲁克。虽然这种版本仍然广泛使用,并且证明了我们这里的观点,但德鲁克的原始名言是“文化——无论如何定义——是 特别持久。”
第三章:源代码管理的价值
在我们迈向 Salesforce DevOps 的技术细节之前,我们应该从探索源代码管理开始。本章将涵盖以下主要内容:
-
为什么源代码管理对实施 DevOps 流程至关重要
-
管理变更的基本 Git 操作
-
成功交付的有效 Git 分支策略与源代码管理
源代码管理,也称为版本控制,是现代 DevOps 的技术支柱,所有其他工具和技术都是建立在这个坚实基础之上的。首先讨论这个话题并了解它的一些常见任务后,你将为本书后续讨论的主题打下坚实的基础,例如 CI/CD 自动化。
技术要求
本章中的示例都与Git源代码管理系统相关,如果你希望跟随学习,建议你安装 Git。同样,推荐使用 Git 托管服务提供商,市面上有许多选择,如 GitHub、GitLab 和 BitBucket。然而,在我们的示例中,我们将使用 GitHub。
源代码管理的重要性
尽管从流程角度来看,建立 DevOps 文化是 DevOps 最重要的方面,正如我们在上一章看到的那样,但可以公平地说,源代码管理是最重要的技术方面。它支撑着所有其他工具和技术,推动着成熟的 DevOps 流程,并支持部署、同行评审、回滚以及作为 CI/CD 过程一部分的自动化。让我们来探索源代码管理及其构建的流程所带来的优势。
协作
DevOps 从根本上是一种协作的软件开发方法,因此有效的协作至关重要。源代码管理使得多个开发者可以同时在同一个代码库上工作,并能够指示他们在开发阶段可能会发生重叠或覆盖彼此的更改。更改稍后会合并,并且当结合适当的审核时,这样的过程能够实现快速开发并减少缺陷,因为变更会在开发周期的早期进行测试和审核。仅当手动和自动检查通过时,代码才会进入更高的环境,最终部署到生产环境。值得注意的是,与开发环境相比,生产环境中的问题更难追踪,并且处理成本更高。
可追溯性
随着良好治理在所有流程和业务中,包括软件开发中的重要性日益增长,软件变更的问责制和审计跟踪的需求也在增加。源代码管理通过记录所有代码和配置的更改历史,帮助实现这一点,详细记录了变更内容、变更人以及(通过提交信息、评论和对如 Jira 等变更管理工具的引用)为什么发生变更。除了这些审计跟踪的好处之外,完整的历史记录还有助于你找到错误和问题的源头。
自动化
DevOps 在很大程度上依赖于自动化,而源代码管理为自动化软件开发中许多过程提供了基础,例如构建、测试和部署代码。例如,借助源代码管理,每当提交代码更改时,便可以自动构建、测试并将代码部署到不同的环境中。
持续集成
持续集成(CI)允许开发人员将他们在开发分支或功能分支中的代码更改集成到共享的集成分支中,然后运行自动化测试,确保这些更改不会破坏现有系统。这个过程得益于源代码管理,它使开发人员能够轻松合并他们的更改并跟踪冲突。通过采用这种技术并定期将更改集成到主代码中,开发人员可以更早地发现问题,从而更容易修复它们。
持续部署
持续部署(CD)是一种实践,当代码更改通过 CI 过程后,它会自动部署到生产环境中。这个过程也得益于源代码管理,它使得部署过程能够实现自动化。这可以通过使用通用的 CI/CD 工具(如 Jenkins、Travis CI 和 CircleCI)或者 Salesforce 特定的工具(如 DevOps Center、Gearset 或 Copado)来实现。无论选择哪种工具,它们都可以配置为在代码通过 CI 过程后自动将代码更改部署到生产环境中。这就是为什么 CI 和 CD 通常被归类为 CI/CD 过程的原因。
持续交付(也称为 CD)
你可能会听到的另一个与 DevOps 相关的 CD 是 持续交付。它与持续部署共享相同的首字母,常常会引起很多混淆。CI/CD 的目标是持续交付:迅速且可靠地向用户交付增强的价值。与持续集成和持续部署不同,持续交付并非工作流程或具体过程,而是定义一种工作文化或方法论。持续交付基于渐进改进的实践,重点在于缩短交付时间并减少开发周期,其中包括来自各方的快速反馈。
这种方法使 Salesforce 团队能够帮助企业迅速且灵活地响应不断变化的优先级和市场前景。CI 和 CD 都是帮助团队实现持续交付的过程。
回滚
版本控制允许轻松回滚,这使得当出现问题时,你可以将代码库恢复到以前的版本。如果生产环境中出现了 bug 或其他问题,能够快速且轻松地回滚更改是非常重要的。版本控制通过保持对所有更改的历史记录,使得在需要时可以轻松回到之前的版本。然而,请记住,并不是所有的内容都可以在 Salesforce 中回滚。例如,如果你尝试回滚包含记录类型或新流程的提交,并且该更改已经部署到组织中,那么你可能会遇到回滚问题。记录类型无法通过元数据 API 移除,流程需要你指定版本号才能删除。
增量开发
另一大源自版本控制驱动的开发和部署方法的显著优势是它鼓励开发人员增量思考——一次提交一个。这进一步支持了之前提到的许多观点——将更改分成更小的增量进行提交,有助于更轻松地管理和合并其他团队成员的工作,减少代码冲突的可能性。它还使调试和跟踪问题变得更容易,因为你可以将当前版本与上一个提交进行比较,以查看两者之间的差异。最后,它鼓励更好的编码标准,因为较小的提交往往会推动更加模块化、解耦的代码架构。
现在我们已经看过使用版本控制的许多优势,以及它在成熟的 DevOps 流程中的重要性,接下来我们将了解一些核心的 Git 任务和命令,这些任务和命令将使版本控制发挥作用。
基本的 Git 操作
在我们深入了解 Git 命令及其应用之前,掌握版本控制的基础知识是至关重要的。
提交
提交是项目文件和目录在特定时间点的快照。每个提交都会分配一个唯一的标识符(称为 SHA 哈希),并包括如作者、时间戳和描述性消息等元数据,用以解释所做的更改。
然而,提交不仅仅是静止的时间点。它们还是反映项目演变的一个大叙事的一部分。在 Git 中,提交是按链条链接的,每个提交都引用其前一个提交。这使得你可以遍历项目历史,比较版本,甚至在必要时回滚更改。
暂存
在你提交更改之前,需要暂存这些更改。暂存区,也称为索引,就像一个准备区,你在提交之前收集和整理更改。暂存更改可以帮助你创建有意义且组织良好的提交,从而清晰地传达你做了什么和为什么这么做。
当你将文件添加到暂存区时,你是在告诉 Git 你希望将该文件的更新包含在下一次提交中。然而,重要的是要注意,Git 会按你暂存该文件时的状态来暂存它。如果你在暂存后继续修改该文件,你需要再次将其暂存,才能将最新的更改包含在下一个提交中。
仓库
仓库,通常通过 git init 命令在包含源代码的目录中创建。
将源代码控制付诸实践
虽然本书并不打算提供 Git 命令和选项的详尽概述,但有一些关键操作构成了 Git 的典型使用方式。
首先,重要的是要注意本地仓库和远程仓库之间的区别,因为许多 Git 命令专门用于在两者之间移动更改。
如名称所示,本地仓库存在于本地开发机器上,可以是一个新初始化的仓库,或者是你从另一个(通常是远程)仓库克隆过来的仓库。在该仓库上执行的操作将保持在本地机器上,直到你将这些更改推送到远程仓库。
远程仓库托管在远程服务器上——可能是使用 Git 托管服务商,或者是公司的物理服务器,可能位于公司自己的数据中心。这个远程仓库作为集中式的“真理来源”,其他开发者可以从中获取你的更改,反之亦然。考虑到本地和远程仓库之间的区别,我们可以开始了解一些常见的 Git 操作及执行这些操作的命令。
初始化新仓库
任何源代码控制工作流的初始步骤是创建一个仓库来存储你的工作,虽然你可能会处理一个已经存在的仓库,但通过在包含源代码的目录中运行以下命令,你可以创建一个全新的空仓库,本地创建的仓库,你可以开始在其中添加文件:
git init
将新文件添加到暂存区
默认情况下,Git 会认为所有文件都是未跟踪的,并且不属于源代码控制。添加文件(也叫做“暂存”文件)意味着这些文件应作为源代码控制的一部分。暂存这些文件是一个两步过程的第一步——首先,我们添加那些我们打算提交的文件;然后,一旦我们确认所有应归为一个提交的文件都已添加,我们就可以继续进行第二步。
你可以像下面这样将单个文件添加到本地 Git 仓库:
git add <file>
或者,你可以像下面这样将当前目录中的所有文件添加进去:
git add .
在这个阶段,直到你提交更改之前,这些更改不会成为本地仓库的一部分,正如下节所示。在这里需要注意的是,当前目录并不等同于本地仓库。尽管本地目录中可能有许多文件,但在你添加并提交这些文件之前,它们并不会成为本地仓库的一部分。
提交之前检查所有内容是否已添加
尽管这不是强制要求,但建议养成检查你希望提交的所有内容是否已被添加的习惯。这可以通过使用git status命令轻松实现。在以下示例输出中,我们可以清楚地看到已添加的更改、已修改但未添加的更改,以及当前未被追踪的文件。最后一种情况可能是因为这些文件已被添加到.gitignore文件中,正如其名称所示,这个文件包含了 Git 应该忽略的文件和路径,或者它们可能是空目录:
图 3.1 – git status 命令的示例输出
提交更改到本地仓库
一旦你使用git add命令暂存了更改,你可以使用git commit命令将这些修改的快照提交到本地仓库。当你提交更改时,重要的是要包含一个描述性的消息,说明提交的目的。这将使你和你的协作人员更容易理解版本控制历史。
许多与 Git 配合使用的工具,包括 GitHub,都会在提交信息中使用某些格式和标签。这些不仅有助于为开发人员提供额外的上下文,还可以驱动工作流集成,例如在错误跟踪工具中。以这种方式编写提交信息需要遵循一定的指南,以保持可读性和有效性。提交信息通常包括一个标题或主题、提交的类型(如feat、fix、docs等)、一个可选的范围来指定变更的区域,以及简洁描述变更的主题。它还可以包含详细的解释性正文和一个引用相关问题 ID 的页脚。主题和标题通常限制为 50 个字符,正文在 72 个字符处换行。提交信息应简洁明了,解释提交的内容和原因。要通过提交信息提交暂存的更改,请使用以下命令:
git commit -m "Commit message"
你可以使用git log命令查看提交到仓库的历史记录。默认情况下,它将显示一个 SHA-1 校验和,以及每次提交的作者、日期和提交信息。然而,Git 提供了许多选项用于过滤和搜索日志,你可以在 Git 的内置文档中找到所有这些选项。
连接你的远程仓库
在我们将更改提交到本地仓库后,我们需要确保远程仓库已正确连接,并且准备好推送我们的更改。如果尚未连接,我们可以使用git remote命令将其连接,并为其提供一个工作别名。通常,这个别名被称为origin,但你也可以使用任何你喜欢的名称。以下是这个命令的示例:
git remote add origin https://github.com/myuser/myrepo.git
该命令通过origin别名连接到我们指定 URL 的远程仓库。
将更改推送到远程仓库
一旦你确认本地的更改是稳定且经过充分测试的,你可以使用git push命令将这些更新传送到远程仓库。这确保了你的更改能够与其他协作者共享,并使得任何有权限访问该仓库的人都可以访问更新后的代码。
要执行git push操作,只需在终端或命令提示符中运行以下命令:
git push
默认情况下,该命令会将更改推送到你本地仓库当前检出的远程仓库分支。但是,如果需要,你也可以指定要推送到的远程仓库和分支:
git push <remote> <branch>
从一个分支合并更改到另一个分支
如果你正在使用一个已存在的 Git 仓库,可能会在与主分支不同的分支上工作——我们将在本章中探讨几种常见的分支策略。
如果是这种情况,你最终需要将更改合并到主分支中,这可以通过git merge命令实现。这确保主分支将你的分支中的更改合并进来,且没有冲突。Git 会自动尝试合并更改,但如果出现冲突,你将需要手动解决。
手动解决冲突涉及到逐一查看包含冲突的文件,比如两个分支都更改了的代码行,并决定最终应该保留哪个版本。Git 会自动在文件中添加<<<<<<<、=======和>>>>>>>标记,表示冲突所在的区域。以下代码片段展示了一个典型的例子:
public class ExampleClass {
public void doSomething() {
<<<<<<<
System.debug('This is the current branch code.');
=======
System.debug('This is the code from the branch being merged.');
>>>>>>> branch-to-merge
}
}
第一个标记表示冲突行的开始。第二个标记作为冲突版本之间的分隔符——标记前的内容属于当前分支,标记后的内容属于待合并的分支。
为了解决冲突,删除冲突标记并编辑代码,使其反映你希望保留的版本。考虑更改的上下文和意图非常重要。因此,建议尽可能与冲突更改的作者进行沟通。
合并策略
在处理分支之间的更改合并时,值得简要了解一下合并策略。这些是 Git 用于确定如何处理冲突更改并将其合并的不同方法,同时也是它如何管理合并过程中不同情况的方式。以下是一些例子,虽然还有许多其他策略:
-
递归:递归策略是 Git 的默认策略,适用于大多数常见场景。它分析两个分支的提交历史,以确定分支分歧前的共同起点,然后应用两个分支的更改。如果在过程中遇到冲突,它会提示进行手动干预。
-
章鱼:章鱼策略用于将多个分支合并为一个分支。例如,你可能想将多个特性分支合并到一个发布分支中。
-
解决:解决策略与递归策略类似,它会尝试自动合并更改,并在检测到冲突时暂停以进行手动干预。然而,这一策略的不同之处在于,它不会递归分析提交历史。
-
我们的:我们的策略旨在优先考虑被合并的分支。与其他策略一样,它会在没有冲突的情况下自动合并,但如果发生冲突,它会丢弃来自进入分支的更改,保留当前版本。正如你可能已经猜到的那样,与此相对的策略是优先考虑进入更改的他们策略。
-
子树:子树合并策略用于将远程仓库的更改合并到当前仓库的子文件夹中。这在非常模块化的项目中或希望将代码库集成到更大项目中的情况中特别有用。
这些策略只是 Git 中可用的合并选项的一部分。你可以通过使用命令行选项或配置设置来选择所需的合并策略。你选择哪种合并策略取决于项目的具体需求和复杂性。
创建新分支
正如我们将在下一节关于分支策略中看到的,当你准备开始处理新特性、修复 bug 或其他更改时,创建一个新分支(通常称为特性分支)是一个常见做法。这样可以确保你的工作与主分支隔离,主分支通常更加稳定并且适用于生产环境。
要创建一个新分支,你可以使用git branch命令,后跟所需的分支名称:
git branch <branch_name>
切换到另一个分支
要从当前使用的分支切换到另一个分支,只需检出该分支,如下所示:
git checkout <branch_name>
另外,你可以使用-b标志通过单个命令创建并切换到新分支:
git checkout -b <branch_name>
现在你已经创建并切换到新的分支,你可以开始修改代码库,而不会影响主分支。一旦工作完成并经过测试,你可以将特性分支合并回主分支,从而确保版本控制历史的清晰和有序。
查看提交历史
git log 命令可以让你查看当前分支的所有提交历史——这包括直接提交到该分支的提交、从其他分支合并过来的提交,或者从创建该分支的原始分支所做的提交。你可以这样查看这些历史记录,包括任何提交消息:
git log
回滚到文件的先前版本
你可以将特定文件回滚到先前的版本,而不是回滚包含多个文件更改的整个提交。通过使用提交历史中显示的提交哈希值和你想恢复的文件名,你可以将文件检出,如下所示:
git checkout <commit_hash> <file>
Git 变基
git rebase 是一种将一个分支的更改集成到另一个分支的方法。它通过将特性分支的提交重放到基础分支之上,替换特性分支为一个更新版本,该版本包含基础分支的所有更改。
git rebase 的主要原则是保持线性历史,这使得理解和追踪代码随时间变化的更改更加容易。线性历史意味着没有合并提交(合并时创建的一种特殊类型的提交,用以维持两个分支历史的延续),只有一条直线的提交记录。
git rebase 还有助于解决在合并时可能出现的冲突。它不会创建合并提交,而是将提交逐一重放到基础分支之上,这样有助于更容易地解决冲突。需要注意的是,git rebase 会修改现有的提交,如果其他人已经拉取了特性分支,可能会引发问题。因此,建议仅在尚未与他人共享的分支上使用 git rebase 。
总结来说,git rebase 是一个强大的命令,可以帮助保持 Git 历史的简洁和易于理解,但应该谨慎使用。现在我们已经了解了基础的 Git 命令及其在工作流中的应用,接下来我们来讨论分支策略。
有效的 Salesforce 分支策略
在版本控制中开发特性时,分支策略为如何使用和管理分支制定了指南。然而,并没有一种适用于所有团队的单一策略。适合你团队的最佳策略将取决于多个因素,比如团队规模、团队结构/复杂性、期望的发布计划和当前的工作流。
例如,较大的团队可能需要更复杂的策略来适应不同的角色,而较简单的策略可能更适合较小的团队。此外,业务需求可能要求特定的发布周期,分支策略应能够满足这些需求。此外,重要的是要考虑您当前的工作流程和环境设置(例如,沙盒的数量)如何与所选择的分支策略保持一致。
Git 作为备份
我们可以考虑的第一个策略是使用 Git 作为你的 Salesforce 元数据的轻量级备份。这种方法通常是团队在开始对其元数据进行版本控制时采取的初始步骤。他们为每个环境建立一个分支,并开始将元数据从他们的组织转移到这些分支上。
虽然这是将元数据输入 Git 的一个很好的初始方法,但是开发生命周期并非真正源驱动。版本控制在这里不是主要的真实来源,而是对已发生更改的回顾记录。它仍然有用,但为了充分利用 Git 的好处,重要的是确保一旦开发了更改,就将它们放入版本控制中,以促进在环境之间的平稳流动。此外,这种模型通常会导致孤立的环境分支,在这些分支中,更改不会在源控制中进行交换。因此,从这种模型过渡到建立源控制作为真实来源的模型可能会具有挑战性。这主要是因为每个组织分支中的同一文件缺乏共享的提交历史,这可能会使 Git 难以处理它们。
例如,使用这种工作流程,很难适应多个功能的并行开发流。在这种模型中没有拉取请求,这使得您可以轻松地将同行评审集成到工作流程中。
此外,由于不会定期从版本控制中部署更改到环境中,因此可能会对通过从版本控制中部署旧版本来回滚发布的能力缺乏信心。
需要记住的是,版本控制主要是为了帮助团队创建、跟踪和部署新功能。不能把它视为灾难恢复目的的 Salesforce 环境的全面备份,因为这是综合 DevOps 策略中备份解决方案的角色。
您可以在以下图表中看到使用 Git 作为备份的示例,以及分支如何反映您的 Salesforce 环境:
图 3.2 – Git 作为备份
基于主干的开发
在主干开发(TBD)中,所有开发者都在一个单独的分支上工作,这个分支被称为主干或主分支。功能开关用于隐藏未完成的工作。分支的生命周期较短,并会尽快合并回主分支。尽管每天(甚至一天多次)将工作合并到主分支的想法可能看起来令人畏惧,但许多团队发现,TBD 的好处远远超过了最初的不适应。采用 TBD 可以促进更多的合作、更高质量的代码以及更加简化的开发过程。
在 TBD 中,开发者为新功能或修复创建分支,但这些分支的生命周期较短。它们会尽快合并回主分支,通常在一天内。为了避免未完成的功能被推送到生产环境,TBD 使用功能开关(也叫功能标志)。这使得团队可以隐藏功能,直到它们准备好投入生产使用。由于每个人都频繁将他们的更改合并到主分支中,因此需要持续集成(CI)。自动化测试确保主分支始终处于可发布状态。你会注意到,这种方法的图示(见图 3.2)与功能分支的图示(见图 3.3)非常相似。两者之间的根本区别在于,TBD 的分支范围更为细化,生命周期也更短:
图 3.3 – TBD
功能分支模型
功能分支模型是一种基本的开发方法,它将 Git 集成到开发过程中,而不仅仅是用于备份。虽然一些团队可能选择更复杂的分支方法,但由于其简单性,功能分支模型是一个很好的起点。主分支是唯一的长期存在的永久分支。当你在开发新功能或修复时,会从主分支创建一个独立的分支,完成后将其合并回主分支。
在这种模型中,最好将功能分支的生命周期保持尽可能短,并在使用后删除它们以保持清洁。大的功能应该分成更小的块,一次实现一个,以缩短反馈周期并减少合并冲突的可能性。需要注意的是,主分支中的任何失败都会阻碍整个发布过程,因为它依赖于所有生产就绪的测试都在每个功能分支上进行,而这并不总是现实的。
主分支通常通过 CI 流程自动部署到预发布环境,使最新版本可供测试。一旦预发布环境中的版本令人满意,就可以从主分支部署到生产环境,将更改发布给最终用户。作为一种选择,在部署到生产环境之前,可以将更改部署到用户验收测试(UAT)或质量保证(QA)环境中进行进一步测试。
以下图示显示了一个典型的功能分支模型,以及该分支中的更改如何重新集成到主分支中,以便在你的 Salesforce 环境中部署。
图 3.4 – 功能分支模型
受保护的主分支模型
受保护的主分支模型类似于功能分支模型,但它包括一个额外的长期存在的集成分支,在合并到主分支之前进行集成。在这种模型中,主分支在所有内容完全测试并准备好发布之前不会更新。主分支是一个更安全的真相来源,因为只有在用户验收测试(UAT)中经过彻底测试的工作才会被纳入该分支。
然而,这种模型的一个缺点是,如果某些更改尚未准备好,无法只传播一部分更改。如果某些工作已经在 UAT 中经过测试和批准,而其他工作还未准备好,那么很难选择性地将更改推广到主分支。相反,必须从发布分支中恢复尚未准备好的功能。这种刚性是许多团队关切的主要问题,这也是为什么这种模型不那么流行的原因。如果你发现自己需要定期选择性地推广更改,那么你可能没有为你的工作方式选择合适的分支策略。
以下图示展示了受保护的主分支方法,其中包括一个单独的集成分支,用于在更改进入生产环境之前进行测试:
图 3.5 – 受保护的主分支模型
扩展的分支模型
在将分支隔离的过程中,扩展的分支模型包括几个额外的长期存在的分支,这些分支分别对应集成和 UAT/QA 环境。功能分支不会直接合并到主分支,而是先合并到集成分支中。为了将已准备好的更改顺利推进到下一个环境,它们会先合并到 UAT/QA 分支,然后再合并到主分支。
这种方法可以更精确地控制哪些更改会被部署到每个环境,并允许对每个请求中的更改进行独立评估。扩展的分支模型非常适合那些更重视门控和质量控制而非频繁发布的团队。然而,像我们之前看到的其他分支策略一样,它也有一些重要的注意事项,特别是当遇到合并冲突时。例如,如果在合并到 UAT 时发现合并冲突,那么必须将整个 UAT 分支合并,以解决冲突,这意味着随后合并到主分支时,UAT 分支的所有内容都会被带入,无论这些内容是否已经准备好发布。
你可以在以下图示中看到分支与 Salesforce 环境之间的关联:
图 3.6 – 扩展分支模型
比较分支策略
那么,让我们回顾并总结这四种方法:
-
将 Git 用作备份是显而易见的:我们使用它作为一种机制,将我们的元数据保存到平台之外,从而允许我们回滚更改——虽然如果变更距离当前有好几次 Git 提交,并且存在深层依赖关系时,这并不容易。它也未能提供源驱动开发方法的主要优势。
-
TBD 方法提供了一系列优势,可以简化并加速软件开发。通过促进短生命周期分支的频繁集成,它大大减少了“合并地狱”现象的发生——即经常让人头痛的冲突变更情况。由于大部分工作都在主分支上进行,变更的可见性也得到了极大的提升,从而使得开发人员可以更清楚地了解变更如何影响项目。TBD 通过消除维护多个长期分支的需求,简化了开发过程,并使主分支始终处于可发布状态,从而支持随时部署,进而实现更快的功能交付。
-
特性分支模型非常适合快速迭代的团队——我们内部也在使用该模型,这让我们能够每天交付变更,或者更频繁地交付。如果你的流程需要更多的阶段性检查和验证,那么这种方式可能不适合你的较长开发周期。
-
保护主分支模型有多个测试环境和一个集成分支来支持它们,这意味着你的主分支或主干分支是事实来源。然而,这个模型仍然充当了一个队列,长周期测试的项目可能会阻塞其他变更,直到它们被推进。
-
扩展分支模型允许更为异步的变更方式,每个独立的工作单元可以在环境中流动。这让类似于“Bob,我们在 Jira 34533 上进展如何?”的问题能够被准确回答,比如“它正在 UAT 环境中,等待生产发布的签署,Sarah。”
总结
在本章中,我们探讨了源代码管理为何对 DevOps 的采用至关重要:
-
协作:DevOps 强调软件开发中的协作。源代码管理允许多个开发人员并行工作在同一代码库上,而无需干扰彼此的更改。通过在后期合并和审查变更,团队能够实现更快的开发并减少缺陷。
-
可追溯性:软件开发中对治理的需求日益增长,这要求具备问责制和审计追踪。源代码管理提供了代码和配置变更的完整历史记录,包括关于谁、什么、为什么的详细信息。这不仅有助于审计,还帮助识别错误和问题的来源。
-
自动化:DevOps 强调自动化,源代码管理作为自动化软件开发过程(如构建、测试和部署代码)的基础。这使得在提交更改到代码库后,可以自动执行这些任务。
-
持续集成:持续集成(CI)使开发人员能够频繁地将代码更改合并到共享仓库,并运行自动化测试,源代码管理在此过程中提供了便利。这种做法有助于及早发现和解决问题,从而简化开发流程。
-
持续部署:持续部署(CD)在通过持续集成(CI)测试后,自动将代码更改部署到生产环境,并通过源代码管理实现自动化。这种 CI 和 CD 的集成形成了 CI/CD 流水线。
-
回滚:源代码管理通过维护代码库历史记录来简化回滚操作,使您能够在生产环境中出现漏洞或问题时迅速恢复到先前的版本。这确保了您可以高效且可靠地处理意外问题。
接下来,我们探讨了一些您在创建 Salesforce 组织更改时可能会定期使用的典型 Git 操作。最后,我们还讨论了一些适用于 Salesforce 开发的常见 Git 分支策略,以及每种策略的优缺点。
在下一章,我们将探讨成熟的 Salesforce DevOps 流程中的下一个基本部分——有效地测试您的更改,以确保高质量的交付物。
第四章:测试你的变更
DevOps 的核心原则之一是能够交付经过严格审查、缺陷更少的强大变更,最终减少变更失败率(CFR)指标。这可以通过测试我们的开发变更在很大程度上实现。
在本章中,我们将探讨对 Salesforce 变更进行全面测试的重要性,适用于你组件的不同测试类型,以及如何确保在 DevOps 过程中进行适当的测试。
我们将覆盖以下主要主题:
-
测试的重要性
-
Apex 测试
-
测试你的Lightning Web 组件(LWCs)
-
测试你的流程
到本章结束时,你应该能够在 Salesforce 中创建并运行测试,覆盖你实现的许多功能,无论是编程实现还是声明式实现。这将有助于你在 DevOps 过程中成熟后交付更高质量的部署。
技术要求
如果你想跟随本章中的示例进行操作,至少需要安装以下软件:
-
Salesforce CLI
-
Visual Studio Code
-
Salesforce 扩展工具适用于 Visual Studio Code
此外,对于测试你的 LWC部分,你需要安装 Node.js(这将包括Node 包管理器(npm))。
测试的重要性
传统的观点认为,软件缺陷越早发现,修复起来越容易,其可能产生的影响和成本也越小。通常称之为左移方法——即在一个从左到右的流程图中,越早处理问题越好——这个理念是通过将强大且全面的测试纳入你的 DevOps 工作流,你有更好的机会尽早发现潜在问题。这种方法不仅适用于 Salesforce 变更的功能测试,也适用于你设计和开发的安全方面——这也是在更广泛的 IT 行业中被称为DevSecOps的部分内容。
如果我们从我们在第二章讨论的 DORA 指标的角度来看测试的影响,我们可以很容易地看出测试直接影响 CFR 指标。简而言之,你的变更经过充分测试,部署到后续环境中的错误发生的可能性就会降低。我在多年的软件开发中常常使用“尽早测试,频繁测试”这句话来很好地总结我的方法。
当我们从更广泛的 DevOps 角度来看待测试时,重要的是要考虑它不仅仅在应用生命周期的开发或交付阶段,而是贯穿于从设计到交付的每一步。作为架构师,我们应该在实施任何变更之前,就开始从思想上测试需求和设计——找出漏洞和缺陷是 Salesforce 架构师最重要的技能之一。通过确保请求有效且其设计经得起推敲,且问题得到了令人满意的解答,您已经在很早之前就测试了这个方案。这被认为是在投入开发者时间(及成本)之前发现缺陷的最经济的时机。它可以被视为软件开发领域的“量好两次,裁剪一次”,这一说法在建筑行业中也常被引用。
测试涉及的方面种类繁多,应作为您整体应用交付模型的一部分进行考虑。我们将在这里讨论一些特定于 Salesforce 平台技术栈的测试,但作为架构师,您应该考虑以下几种测试类型,以全面了解测试。
集成测试
彻底的集成测试对于验证不同组件和系统能否按预期协同工作至关重要。对于 Salesforce 项目,关键的集成测试包括 Salesforce 与外部数据库、第三方 Web 服务之间的连接,Salesforce 产品(如 Sales Cloud 和 Service Cloud)之间的交互,以及自定义 Lightning 组件或其他自定义功能的测试。
使用自动化的 API 和 UI 测试、端到端(E2E)流程验证,以及人工抽查相结合的方式,确保所有集成点从端到端始终按设计功能运作。跨系统导入和导出数据,检查数据的准确性和完整性。如有可能,向 Web 服务发送测试请求,验证响应处理,或者作为备选,提供这些请求的模拟响应。
回归测试
回归测试帮助验证在进行更改后,现有的功能和集成功能是否仍按预期工作。在部署重大更新、新功能或结构性变更(如修改权限或记录共享规则)后,应优先进行回归测试。通过构建自动化的回归测试套件,使其快速且频繁地运行,重点关注最可能受到更改影响的关键业务流程和集成点,您可以快速检查并解决任何破坏性变更。
使用自动化 UI 测试、Apex 测试以验证逻辑和处理程序、跨浏览器测试,以及 Salesforce API 检查数据验证,并将回归测试集成到部署流水线中,自动运行。
回归测试能够确保系统在持续改进和变更过程中保持稳定。
用户验收测试
用户验收测试(UAT)通常需要一个专门的 Salesforce 沙箱环境,里面有测试数据、角色和模拟的真实使用模式的流程。要让真实用户参与 UAT,以验证新功能是否满足业务需求,才能正式发布。在 业务单元(BUs)中,找出关键用户,作为 UAT 测试人员,他们对需求和工作流程有深入了解。
一定要制定正式的测试计划和报告,以确保充分的真实环境验证。在 UAT 测试过程开始之前,您应当为测试人员提供账户访问权限、样本数据和清晰的测试场景,并将其映射到业务用例。
跟踪并分类所有在 UAT 过程中发现的问题,明确与用户的需求,并在继续生产部署之前解决这些问题。需要注意的是,在许多较大的组织中,这一过程通常由业务分析师或专门的测试人员完成,而不是架构师(架构师的角色更多是监督过程并确保其顺利进行)。
大规模测试
特殊测试是必需的,以确认 Salesforce 平台能够处理大数据量和高用户负载。在测试环境中使用实际的大型数据集来验证性能和在大规模下的稳定性。将数据库加载到预期的最大数据大小,并导入具有代表性的样本数据。使用性能测试工具来模拟并发用户的高峰数量,识别治理限制或瓶颈。优化配置以支持缓存、索引和可扩展性最佳实践。随着数据量的增加,检查性能是否有所下降,并根据需要进行调优或增加资源。通过大规模测试模拟生产级使用情况,有助于验证系统是否能支持业务增长。
在 Salesforce DevOps 的世界里,最常见的两种测试类型是单元测试和端到端(E2E)测试,但正如我们接下来将看到的,其他重要的测试,如集成测试和回归测试,也应该纳入考虑范围。
单元测试集中于验证应用程序中的各个独立功能——这些功能通常与您正在开发的具体更改相关。需要注意的是,Salesforce 强制要求在整个组织内,Apex 测试覆盖率至少达到 75% 才能进行生产部署,更重要的是,这并不保证功能是正确的。编写不好的测试可能会掩盖或扭曲实际问题,因此单元测试只能被视为整体测试策略的一部分。此外,如果您指定了某些特定的测试类作为生产部署的一部分,那么每个被部署的 Apex 类都需要单独达到 75% 以上的覆盖率,而不是依赖于组织级或甚至部署包级的平均覆盖率。这更加证明了需要尽可能争取更高的覆盖率百分比。
单元测试在你将应用程序构建为小的、可测试的单元时效果最佳,而不是将其构建为单体的 Apex 类、流程,甚至是对象。创建简短、快速的单元测试,这些测试可以轻松执行,能够激励开发人员将其纳入开发、回归测试和持续集成(CI)过程中。因此,缺陷会被更早发现并解决。
Apex 测试
编写没有适当测试的 Apex 代码可能会导致问题,比如缺陷和错误,这可能会负面影响用户体验,并最终损害项目的整体成功。在这方面,Apex 单元测试是开发过程中至关重要的一部分,帮助确保代码按预期运行,满足要求,并能处理不同的场景。在这方面,Apex 单元测试对于在 Salesforce 中创建高质量、强健且可维护的代码至关重要。
这些测试应该设计成模拟正面和负面场景。这意味着代码不仅要测试它是否能按预期完成任务,还要测试它不会做它不应该做的事。此外,Apex 单元测试应该编写成在单一上下文或批量上下文中进行测试,也就是说,它们可以测试单个记录或一次多个记录。为了提高测试效率并隔离被测代码,可以使用模拟和桩来模拟外部依赖,例如 Web 服务或数据库操作。通过编写覆盖所有可能场景的全面单元测试,并采用如模拟测试等最佳实践,Salesforce 开发人员可以构建可靠、可维护和可扩展的应用程序。
如前所述,Salesforce 要求代码的单元测试覆盖率至少为 75%,但作为优秀的架构师,我们应该始终争取尽可能接近 100%的覆盖率。现实情况是,确实会有一些角落案例是无法通过单元测试触及的——通过瞄准 100%的覆盖率,这些案例会落入高标准和要求的 75%之间的缓冲区,因此我们在编写良好的单元测试时,永远不应该有不足的覆盖率。
为了说明一个简单的 Apex 单元测试示例,首先,考虑以下 Apex 类。它包含一个静态方法,用于计算购物车中产品的总价格。这些产品使用一个Product__c自定义对象,该对象包含一个Price__c自定义字段——为了示例说明,这个自定义对象比标准的Product2对象及其关联对象要简单得多:
public class ShoppingCart {
public static Decimal calculateTotal(List<Product__c> products) {
Decimal total = 0;
if (products != null) {
for (Product__c p : products) {
if (p.Price__c != null) {
total += p.Price__c;
}
}
}
return total;
}
}
一个初步尝试的对应单元测试类,包含单个测试和批量化测试,覆盖了正面和负面场景,可能看起来是这样的:
@isTest
private class ShoppingCartTest {
@isTest
static void SingleProduct() {
// Create a single product
Product__c p = new Product__c(Description__c='Product A',
Price__c=100);
insert p;
// Calculate the total price
Decimal total = ShoppingCart.calculateTotal(new
List<Product__c>{p});
// Verify that the total is correct
Assert.areEqual(100, total, 'Total should be 100');
}
@isTest
static void testMultipleProducts() {
// Create multiple products
List<Product__c> products = new List<Product__c>{
new Product__c(Description__c='Product A', Price__c=100),
new Product__c(Description__c='Product B', Price__c=50)
};
insert products;
// Calculate the total price
Decimal total = ShoppingCart.calculateTotal(products);
// Verify that the total is correct
Assert.areEqual(150, total, 'Total should be 150');
}
@isTest
static void testNullProducts() {
// Calculate the total price with null products
Decimal total = ShoppingCart.calculateTotal(null);
// Verify that the total is zero
Assert.areEqual(0, total, 'Total should be 0');
}
@isTest
static void testProductsWithoutPrice() {
// Create a product without a price
Product__c p = new Product__c(Description__c='Product A');
insert p;
// Calculate the total price
Decimal total = ShoppingCart.calculateTotal(new
List<Product__c>{p});
// Verify that the total is zero
Assert.areEqual(0, total, 'Total should be 0');
}
}
在这个示例中,单元测试类包含四个测试方法:testSingleProduct、testMultipleProducts、testNullProducts 和 testProductsWithoutPrice。前两个方法分别使用不同数量的产品来测试 calculateTotal 方法,而第三个和第四个方法则分别使用空值和不完整的产品数据来测试。使用单个和批量化测试相结合,确保代码能够处理不同的场景并良好扩展。此外,正面和负面流程的结合使用有助于确保代码能够处理预期的和意外的输入数据。
尽管这个测试类能够正常工作,但许多代码场景将受益于一个 @testSetup 方法,用于创建测试中使用的数据。测试结束时,这些数据会被回滚。
如果我们考虑以下触发器和相应的处理程序类——这个示例是用于说明,并不是一个实际的应用案例——我们可以为它创建一个利用 @testSetup 注解的测试类。触发器、处理程序类及其测试在这里显示:
trigger ProductTrigger on Product__c (before insert, before update, after insert, after update)
{
if (trigger.isBefore)
{
if (trigger.isInsert)
{
//before insert logic
}
else if (trigger.isUpdate)
{
//before update logic
}
}
else if (trigger.isAfter)
{
if(trigger.isInsert)
{
//after insert logic
}
else if (trigger.isUpdate)
{
//after update logic
}
}
}
public with sharing class ProductTriggerHandler
{
public static void beforeInsert(List<Product__c> products)
{
Decimal total = 0.0;
for(Product__c prod : products)
{
total += prod.Price__c;
}
System.debug(total);
}
}
@isTest
public with sharing class ProductTriggerHandlerTest
{
@TestSetup
static void setup()
{
// Create multiple products
List<Product__c> products = new List<Product__c>{
new Product__c(Description__c='Product A', Price__c=100),
new Product__c(Description__c='Product B', Price__c=50)
};
insert products;
}
@isTest
static void testTotal()
{
List<Product__c> products = [SELECT Id, Description__c,
Price__c from Product__c];
Decimal total = 0.0;
test.startTest();
for(Product__c prod : products)
{
total += prod.Price__c;
}
Assert.areEqual(150, total, 'Total should be 150');
}
}
使用这种方法,@testSetup 注解用于创建多个产品,这些产品在后续的测试方法中使用。这避免了在每个测试方法中重复创建产品记录,使测试代码更加高效且易于阅读。我们原始测试类中的前两个测试方法现在依赖 @testSetup 方法来创建产品并计算总价格,而剩余的方法则测试不同的场景。使用 @testSetup 有助于确保测试数据的一致性,使得测试更可靠。
我们可以通过使用 test.startTest() 和 test.stopTest() 方法进一步改进这个测试类。这些方法用于分隔每个测试方法的设置阶段和执行阶段,应该在专门执行我们希望测试的代码之前和之后立即调用。这可以确保通过 Limits.get*() 方法捕获的性能指标以及由测试方法启动的异步操作是独立的,不会与测试执行前后进行的其他操作混合。使用 test.startTest() 和 test.stopTest() 也有助于避免在测试执行过程中触发治理限制,特别是在测试批量数据操作时。
在 Apex 单元测试中,仔细和勤奋地测试是非常重要的,但正如我们将在下一部分看到的,这不应是唯一应用质量承诺的地方。我们将从测试 LWC 开始。
测试你的 LWC(Lightning Web Components)
虽然 Salesforce 仍然有多种方法来开发 Lightning 组件,但我们将专注于测试 LWC,而不是较旧的 Aura 组件。Salesforce 于 2018 年 12 月发布了 LWC,并在 Salesforce Spring ’19 版本中推出。这一消息在 2018 年 12 月 13 日由 Salesforce 发布的博客文章中宣布,标题为《Introducing Lightning Web Components》,可在 developer.salesforce.com/blogs/2018/12/introducing-lightning-web-components 阅读。
在测试 LWC 时,我们可以利用这种组件架构基于更常见的 JavaScript 标准和开放框架的事实。这使得我们能够使用流行的 Jest 测试框架来编写单元测试(jestjs.io/),该框架在 Salesforce 之外的更广泛的 JavaScript 社区中也已经在使用。Jest 本身是用 JavaScript 编写的,使用 Node.js 引擎执行,并使用 npm 进行安装和管理其依赖项。
在 Salesforce 的世界里,有一个名为 sfdx-lwc-jest 的插件,它可以让你轻松地将 Jest 及其依赖项添加到 Salesforce 项目中。
如果你在项目目录中运行以下命令,它将安装必要的 npm 工具和 @salesforce/sfdx-lwc-jest 包:
sf force lightning lwc test setup
在你的项目中设置了运行 Jest 测试的能力后,你需要为 LWC 配置一些测试。这些测试在开发机器上本地运行,独立于 Salesforce,这使得在项目开发阶段运行它们更加容易,同时也便于将它们作为你在 DevOps 流水线中添加的任何测试自动化的一部分。
如果你使用标准模板创建了一个 SFDX 项目,它已经准备好了所有这些可以编写的 Jest 测试。project.json 文件和 .forceignore 文件已经配置好。这也会创建一个 __tests__ 目录和一个测试文件框架。然而,如果你没有从模板创建项目,接下来的步骤将详细介绍如何创建适当的结构——在大多数情况下,模板会为你处理这些。
你的第一项任务应该是在每个组件的顶级文件夹下创建一个 __tests__ 文件夹。例如,考虑这个 LWC 文件夹结构示例:
图 4.1 – 没有测试的示例 LWC 文件夹结构
在这个示例中,添加所需的 __tests__ 文件夹后,结构会变成这样:
图 4.2 – 相同的 LWC 文件夹结构,包含测试文件夹和文件
您还应该在项目的.forceignore文件中添加一个通配符路径指向__tests__文件夹,因为您不应该将 Jest 测试部署到 Salesforce 组织中——事实上,如果您尝试这么做,系统会抛出错误。将以下行添加到.forceignore文件中应该能解决这个问题:
**/``__tests__/**
接下来,您需要在项目的package.json文件中的script部分添加以下行:
"``test:unit": "sfdx-lwc-jest"
您的项目现在已经配置好可以运行 Jest 测试,接下来我们将讨论如何为您的组件构建这些测试。
一个 Jest 测试示例
现在我们已经设置好了运行 Jest 测试的前提条件,接下来可以查看之前展示的teamComponent组件的一个轻量级示例测试:
import { createElement } from 'lwc';
import teamComponent from 'c/teamComponent';
describe('c-team-component', () => {
afterEach(() => {
// The jsdom instance is shared across test cases in a single
// file so reset the DOM
while (document.body.firstChild) {
document.body.removeChild(document.body.firstChild);
}
});
it('renders the correct message', () => {
const element = createElement('c-team-component', {
is: teamComponent
});
document.body.appendChild(element);
const pElement = element.shadowRoot.querySelector('p');
expect(pElement.textContent).toBe('Welcome to the team!');
});
});
在这个测试类中,我们从 LWC 导入createElement函数来创建teamComponent组件的实例,然后使用 Jest 的describe和it函数定义一个测试用例,检查组件是否正确渲染消息。
afterEach函数用于在测试用例之间重置 DOM,以确保每个测试用例从干净的状态开始。
在it函数中,我们使用createElement创建teamComponent组件的实例,使用document.body.appendChild将其添加到 DOM 中,然后使用querySelector查找包含消息的元素。最后,我们使用 Jest 的 expect 函数检查p元素的文本内容是否等于欢迎加入 团队!。
这只是一个示例,您的测试类可能需要更复杂,涵盖更多的用例,但这应该能给您一个关于如何开始使用 Jest 为 LWC 编写单元测试的概念。Salesforce Trailhead 有更多关于测试 LWC 的详细示例,包括使用@wire服务的示例。现在我们已经编写了 Jest 测试,让我们来看看如何运行这些测试来验证我们的代码。
运行 Jest 测试
要使用 Jest 在 Salesforce 项目中测试 LWC,您可以按照以下步骤操作:
-
在终端中导航到 LWC 组件的根目录。
-
运行
npm run test命令。这将执行 Jest 测试运行器并运行__tests__目录中的任何测试,或与正在测试的 LWC 在同一目录中的测试。 -
Jest 测试运行器将在终端中显示测试结果。如果任何测试失败,Jest 运行器会输出有关测试失败的详细信息。
-
您还可以通过指定要运行的测试文件或测试套件的名称来运行单个测试。例如,您可以通过运行
npm run testteamComponent.test.js命令来运行名为teamComponent.test.js的测试。 -
您可以使用额外的选项来定制 Jest 的行为,例如在
watch模式下运行测试或生成代码覆盖率报告。您可以在 Jest 文档中找到更多关于 Jest 选项的信息。
到目前为止,我们已经有了测试我们的 LWC(Lightning Web Component)的方法,但这只是拼图的一部分。在接下来的部分,我们将开始探索如何测试 Salesforce 提供的主要声明式工具——流程。
测试你的流程
流程是 Salesforce 中另一种非常常见的开发复杂功能的方式,虽然它们属于点击而非代码的 Salesforce 开发类别,但对它们进行严格的测试与基于代码的解决方案同样重要。
在流程构建器中,你可以在不离开界面的情况下测试你的流程。UI 中有两个按钮用于测试你的流程:运行和调试。我们来看看它们的作用:
-
运行按钮执行的是当前在编辑器中打开的、最近保存的版本的流程。
-
调试按钮提供了比运行按钮更多的功能。除了运行流程,调试按钮还允许你为流程的输入变量输入值,并在流程执行过程中查看调试细节。这使你可以验证流程是如何处理数据的,并找出任何问题或错误。
每次在 Salesforce 中运行流程时,它都会启动一个流程访谈。流程访谈是流程的一个独特实例,根据提供的参数沿特定路径执行。这些参数可以包括输入变量或屏幕上的组件,这些都可以引导访谈沿不同路径执行流程并触发不同的动作。
通过创建覆盖正面和负面场景的流程访谈,你可以像 Apex 测试一样测试流程的条件。然而,将一个流程拆分成更小的测试可能具有挑战性,因为一个流程访谈测试的是整个流程,而不仅仅是一次决策。你可能需要创建多个流程访谈来覆盖流程中的所有可能路径。
为了简化测试并确保全面覆盖,将流程拆分成子流程可能是有益的。这个架构方法有助于创建更易于管理和高效的测试。
从 Summer ’22 Salesforce 版本开始,您可以将这些流程访谈转换为流程测试。在 Salesforce 的流程调试器中成功执行流程访谈后,页面右上角会出现一个转换为测试操作,紧挨着编辑流程。要将调试运行转换为流程测试,请点击转换为测试,然后会在弹出窗口中出现一个新的测试界面。每个流程最多可以创建 200 个测试,因此应该能够为流程的每个路径创建测试:
图 4.3 – 创建新的流程测试
在 Salesforce 中测试流程时,每个断言都会被评估,以确认流程是否按预期行为执行,如下图所示。然而,值得注意的是,测试只能验证流程元素是否执行,以及流程资源值是否正确设置:
图 4.4 – 为我们的新测试提供断言,以验证我们的流。
在撰写本文时,架构师在评估流测试作为整体 DevOps 设计的一部分时应考虑以下一些重要事项:
-
流测试仅适用于记录触发的流。
-
流测试不支持当记录被删除时运行的流。
-
流测试不支持异步运行的流路径。
-
流测试无法作为部署的一部分自动触发。
-
流测试可以基于特定的记录 ID,但这可能使测试变得脆弱,因为记录 ID 在其他环境中并不保证存在。
-
流测试不计入流测试覆盖率要求。
-
这一点尤其值得注意,因为如果你希望能够将流部署为活动,它们需要像 Apex 代码一样有测试覆盖(并且测试覆盖的最低标准为 75%)。
这一过程不如代码那样成熟,但作为参考,对于活动流程和自动启动流,至少一个 Apex 测试必须达到流测试所需的测试覆盖率百分比。然而,值得注意的是,流测试覆盖率要求不适用于包含屏幕的流。
流测试的不成熟主要体现在流测试在 Flow Builder UI 中生成的测试与覆盖范围所需的测试之间缺乏一致性。这些测试不仅需要以 Apex 单元测试的形式编写代码,而且要查看你组织中流的当前代码覆盖率,还需要查询FlowTestCoverage对象——例如,从开发者控制台中查询。
要确定 Salesforce 中流的测试覆盖率,你需要考虑所有活动版本,无论它们是否有测试覆盖,以及所有最新版本且具有测试覆盖的非活动版本。以下是为此目的提供的示例查询——要运行这些查询,你需要确保在开发者控制台中选中使用工具 API框。
首先,你需要确定具有测试覆盖的流的数量(每个流的最新版本),如下所示:
SELECT count_distinct(FlowVersionId)
FROM FlowTestCoverage
然后,获取所有活动版本的流的数量——无论是否有测试覆盖——以及那些是具有测试覆盖的最新版本的非活动版本:
SELECT count_distinct(Id)
FROM Flow
WHERE Status = 'Active' AND Id NOT IN (
SELECT FlowVersionId
FROM FlowTestCoverage )
要确定 Salesforce 流的测试覆盖率百分比,将具有测试覆盖的最新版本流的数量(第二个脚本)除以所有活动和非活动版本中具有测试覆盖的总和,同时包括那些没有测试覆盖的版本(初始脚本)。如果这一切听起来过于复杂,你是对的,我们只能希望随着 Salesforce 版本的更新,这一领域能够得到改进。
总结
在本章中,我们探讨了为什么测试变更是 Salesforce DevOps 的核心原则。我们还深入分析了一些示例测试,展示了根据你实施 Salesforce 功能的不同方法——Apex 代码、LWC 或流程——它们在构建上的差异。
现在我们已经了解了构建 Salesforce DevOps 流程的一些基础要素——文化、版本控制和强大的测试——在下一章中,我们将开始探讨如何通过一些示例工作流和日常交付场景,结合这些元素,使用 SFDX 工具和 Git 来实现这一目标。虽然这些工具只是 Salesforce DevOps 的众多方法之一,但通过将我们讨论的一些原则展示为现实世界的例子,你将能看到一个典型的工作流如何运作。
第五章:使用 SFDX 进行日常交付
在本章中,我们将看到如何应用到目前为止学到的知识,使用 SFDX 工具套件结合 Visual Studio Code 和 Git 来管理变更交付。这并不是进行 Salesforce DevOps 的唯一方法,假设是从头开始启动一个全新的项目,但它将展示一些常见的任务和原则。
我们将涵盖以下主要主题:
-
设置工具和项目
-
使用 Git 和 SFDX 的变更生命周期
-
沙箱与临时组织
在本章结束时,你应该能够在自己的 Salesforce 组织中复制一个简单的工作流,该工作流用于从 Jira 或 Asana 等票务系统中提取工作项,创建一个新的功能分支,使用 SFDX 和 VS Code 进行修改,并再次将代码提交。这是 DevOps 最直接的方法,将为你提供坚实的实践基础。
技术要求
如果你想跟随本章的示例,至少需要安装以下内容:
-
Salesforce CLI
-
VS Code
-
VS Code 的 Salesforce 扩展
你还需要一个 GitHub 账户(github.com/),用来创建新的 Git 仓库,以及在本地计算机上安装 Git(git-scm.com/)。
设置工具和项目
在大多数实际场景中,你的工具和项目可能已经准备好用于现有实现的开发,但我们将从零开始设置所有内容,这样如果你想按照示例工作流操作,甚至可以从全新的开发者版 Salesforce 组织开始。
Salesforce CLI
Salesforce CLI 是与 Salesforce 组织互动的主要工具,也是 CI/CD 过程自动化的基础。
图 5.1 – Salesforce CLI 下载页面概览
要在 Windows、macOS 或 Linux 上安装 Salesforce CLI,请按照所需操作系统的说明进行操作。
Windows
-
访问 Salesforce CLI 下载页面:
developer.salesforce.com/tools/sfdxcli。 -
点击Windows 安装程序链接下载 Windows 安装程序。
-
运行下载的可执行文件(
.exe)以启动安装过程。 -
跟随安装向导,接受许可协议,并选择所需的设置。默认设置通常对大多数用户来说足够了。
-
通过点击安装,然后点击完成来完成安装过程。
-
打开命令提示符或 PowerShell,输入
sfdx --version来验证安装。如果安装成功,你应该能看到已安装的 Salesforce CLI 版本。
图 5.2 – 检查 Windows 上 Salesforce CLI 的安装
macOS
-
访问 Salesforce CLI 下载页面:
developer.salesforce.com/tools/sfdxcli。 -
点击 MacOS 安装程序 链接,下载适用于你 Mac 类型的 macOS 安装程序。
-
打开下载的
.pkg文件以开始安装过程。 -
跟随安装向导,接受许可协议,并选择所需的设置。默认设置通常对于大多数用户来说是足够的。
-
通过点击 安装 然后点击 关闭 来完成安装过程。
-
打开终端并输入
sfdx --version来验证安装。如果安装成功,你应该能看到已安装的 Salesforce CLI 版本。
图 5.3 – 检查 macOS 上 Salesforce CLI 的安装是否成功
Linux
Salesforce CLI 的 Linux 版本提供为 tarball 格式。你可以在这里找到适合你系统架构的 tarball 下载 URL。
| 架构 | 清单文件 |
|---|---|
| x64 | developer.salesforce.com/media/salesforce-cli/sfdx/channels/stable/sfdx-linux-x64.tar.xz |
| Arm | developer.salesforce.com/media/salesforce-cli/sfdx/channels/stable/sfdx-linux-arm.tar.xz |
表 5.1 – Linux 安装包的清单文件
-
要下载这些 tarballs 之一,可以使用
wget命令。例如,对于 x64 平台,使用以下命令:sfdx:mkdir ~/sfdx
-
解压你下载的 tarball 版本内容:
tar xJf sfdx-linux-x64.tar.xz -C ~/sfdx --``strip-components 1
-C 标志将内容提取到 sfdx 目录中,而 --strip-components 1 会移除根路径组件。
-
修改你的 PATH 环境变量以加入 Salesforce CLI 的
bin目录。例如,要配置当前终端会话,使用以下命令:~/.bashrc or ~/.bash_profile file:使用
sfdx --version来验证安装。如果安装成功,你应该能看到已安装的 Salesforce CLI 版本。
图 5.4 – 验证 CLI 安装
Git
要在 Windows、macOS 或 Ubuntu Linux 上安装 Git,请根据相应操作系统的说明进行操作。对于其他 Linux 发行版,你可能需要搜索与你的包管理系统相匹配的文档。
图 5.5 – Git 客户端下载页面
Windows
- 从官方网站下载 Git for Windows 安装程序:
-
运行下载的可执行文件(
.exe)以启动安装过程。 -
按照安装向导进行操作,选择所需的设置。默认设置通常对大多数用户来说足够。
-
通过点击安装然后点击完成来完成安装过程。
-
要验证安装,请通过在开始菜单中搜索或通过右键单击文件夹中的上下文菜单选择Git Bash Here打开 Git Bash 终端。
-
在 Git Bash 终端中输入
git --version并按Enter键。如果安装成功,你应该能看到已安装的 Git 版本。
图 5.6 – 确认在 Windows 上成功安装 Git
macOS
-
通过打开终端应用并输入
git --version来检查 Git 是否已安装。如果 Git 已安装,你将看到版本号。如果没有,继续进行下一步。 -
按照官方网站上的说明安装Homebrew,这是 macOS 的一个包管理器:
brew.sh/。 -
安装 Homebrew 后,打开终端并输入
brew install git。 -
等待安装过程完成。
-
通过在终端中输入
git --version来验证安装。如果安装成功,你应该能看到已安装的 Git 版本。
图 5.7 – 确认在 macOS 上成功安装 Git
Ubuntu Linux
-
打开终端(Ctrl + Alt + T)。
-
通过输入
sudo apt update并按Enter键更新包列表。 -
通过输入
sudo apt install git并按Enter键来安装 Git。 -
在提示时输入
Y并按Enter键来确认安装。 -
等待安装过程完成。
-
通过在终端中输入
git --version来验证安装。如果安装成功,你应该能看到已安装的 Git 版本。
图 5.8 – 确认在 Linux 上成功安装 Git
VS Code 和扩展
Microsoft VS Code 适用于 Windows、macOS 和 Linux 系统。安装程序可以从code.visualstudio.com/download获取—只需按照你的操作系统的说明进行操作。
对于使用 VS Code 进行 Salesforce 开发,最重要的是一些允许直接在 IDE 内与 Git 和 SFDX 集成的扩展:
-
打开 VS Code。
-
单击侧边栏上的扩展视图图标,或按Ctrl + Shift + X(Windows/Linux)或Cmd + Shift + X(Mac)打开扩展面板。
-
在搜索栏中搜索
Salesforce Extension Pack。 -
点击 Salesforce Extension Pack 上的 Install 按钮,这个扩展包由 Salesforce 提供。它将安装一系列扩展,包括 Salesforce CLI 集成、Apex、Aura 组件、Lightning Web 组件等。
创建一个新的 SFDX 项目并将其连接到你的 Salesforce 组织
现在我们已经安装了所有必需的工具,接下来可以开始构建一个可以工作的项目。我们将在 VS Code 中创建一个新的 SFDX 项目,并将其连接到我们的 Salesforce 环境。我们还会将它连接到我们的 Git 源代码控制,这样我们就能真正以源驱动的方式工作。让我们来看看将一切连接起来所需的步骤:
-
使用命令面板设置 SFDX 项目:
-
使用 Ctrl + Shift + P(Windows/Linux)或 Cmd + Shift + P(Mac)打开命令面板。
-
输入
SFDX: Create Project并按下 Enter 键。 -
选择 Standard 作为项目模板,并按下 Enter 键。
-
输入你希望为项目命名的名称,并按下 Enter 键。
-
选择一个文件夹来存储你的 SFDX 项目,并按下 Enter 键。这将在指定的文件夹中生成一个新的 SFDX 项目结构。
-
-
使用命令面板设置项目的默认组织:
-
使用 Ctrl + Shift + P(Windows/Linux)或 Cmd + Shift + P(Mac)打开命令面板。
-
输入
SFDX,然后设置一个默认的组织并按下 Enter 键。 -
选择一个别名,用于在认证你的 Salesforce 组织时使用。
-
现在你已经使用命令面板安装并设置了 Salesforce 的 VS Code 扩展,并且准备开始开发 Salesforce 应用程序。
Git 和 SFDX 的变更生命周期
在许多组织中,团队使用工作流管理系统,如 Jira 或 Asana,来捕捉、完善和分配开发团队的工作项。在这个示例中,我们假设使用的是 Jira,但这纯粹是为了说明目的,以复制一个相对典型的现实场景。要跟随这些示例,完全不必使用 Jira 或任何等效系统。我们将在 第八章 中更详细地探讨票务系统。
获取一个可以使用的 Git 仓库
在 第三章 中,我们查看了最常见的 Git 操作及其对应的命令。在大多数现实场景中,你可能已经有一个现成的仓库可以使用。然而,也可能有一些场景,你是第一次使用 Git 开始一个项目,那么我们来看看准备 Git 进行工作的主要方法:
-
git init会在你的机器上创建一个全新的本地仓库以供使用。此时,还没有对应的远程仓库。如果你需要提醒如何连接一个远程仓库,可以参考 第三章,例如在 GitHub 上的操作。 -
git clone将在您的本地计算机上创建一个远程仓库的副本——包括版本历史、所有分支和提交。它会为您创建正确的目录结构,准备好进行工作。 -
git checkout用于在现有仓库中切换分支。当您使用此命令时,您的本地工作文件夹将更新为该分支的内容。
获取主分支的最新更改
在开发前获取最新的主分支更改,可以确保代码库的最新性,最小化合并冲突,并简化新功能或修复的集成:
-
在 VS Code 中,点击左侧边栏的 源代码管理 图标。
-
点击顶部的 …(省略号)按钮,并选择 Pull 以获取并合并主分支的最新更改。
创建一个新的功能分支
功能分支模型是一种简单的基于 Git 的开发方法,非常适合初学者。它在主分支上维护最新的元数据,主分支应始终处于发布就绪状态。什么是“发布就绪”或“生产就绪”的定义可能会有很大差异,主要取决于所应用的测试级别,既包括单个更改的测试,也包括生产系统及其可能集成的整体测试。为了演示工作流,我们将极大地简化我们的定义,表示更改已在开发组织中进行了功能测试,所有代码审查(包括自动和手动)已完成,并且拉取请求已被批准。
开发人员从主分支创建新分支来实现功能或修复,完成后将其合并回主分支。短期存在的功能分支可以最小化合并冲突,并促进整洁性。较小的交付物减少了反馈周期的长度。要在 VS Code 中创建功能分支,请按照以下步骤操作:
-
在 源代码管理 面板中,点击窗口左下角的分支图标。
-
输入新功能分支的名称(例如,
feature/JIRA-1234),然后按 Enter 键创建并切换到新分支。
正在处理您的更改
现在,您应该能够开始在功能分支上进行开发工作。这可以是在连接的 Salesforce 组织中的配置工作,或是在 Salesforce IDE 中进行的基于代码的开发。
Salesforce 的 VS Code 扩展简化了在本地计算机和开发组织之间来回移动元数据更改的过程。许多底层的 Salesforce CLI 命令可以通过组织浏览器、命令面板,或右键点击文件时作为上下文敏感菜单选项使用。
获取元数据
-
在 VS Code 的侧边面板中打开组织浏览器(您可以通过一个类似云的图标找到它)。
-
如果这是您第一次使用组织浏览器,或者如果您的组织的元数据发生了变化,点击刷新图标以从您的组织中获取元数据。
-
Org 浏览器显示元数据类型的列表。您可以点击元数据类型旁边的箭头展开它,并查看该类型的各个组件。
-
要检索元数据组件,请点击组件名称旁边的云下载图标。这会将组件检索并添加到您的本地项目中。
部署元数据
-
导航到您在本地项目结构中要部署的文件或文件夹。
-
右键单击选中的项目。
-
从上下文菜单中选择SFDX: 部署源代码到组织命令。这会将元数据部署到您的组织中。
-
请注意,Org 浏览器并不直接支持部署,但会使用 VS Code 中 Salesforce 扩展的标准部署命令。
一旦开发完成,请在 Salesforce 中使用 Scratch Org 或沙盒测试您的更改,具体使用哪一种取决于情况。我们将在本章后续部分对这两种 Salesforce 开发环境的差异进行详细讨论。
提交您的更改
提交更改的两步过程包括首先暂存更改,然后执行提交。暂存是选择更改进行提交,而提交则是将已暂存的更改记录为本地仓库中的新快照,从而保持开发历史。您可以这样完成暂存和提交您的更改:
-
在源代码管理面板中,检查您所做的更改。
-
通过点击每个已更改文件旁边的**+图标,或点击CHANGES旁边的+**图标以暂存所有更改。
-
输入一个有意义的提交信息,描述与 Jira 票据相关的更改(例如,“
JIRA-1234: 实现了新特性”)。 -
点击顶部的对勾图标,将更改提交到您的功能分支。
将您的功能分支推送到远程仓库
一旦我们的更改添加到本地 Git 中,我们可以按如下方式将这些更改推送到远程仓库:
-
在源代码管理面板中,点击顶部的**…(省略号)按钮,并选择推送**。
-
如果提示,请选择您的功能分支(例如,“
feature/JIRA-1234”)并将其推送到远程仓库。
创建拉取请求
在 Git 中创建拉取请求是一个协作过程,开发者提出将其更改从一个分支合并到另一个分支,通常是从功能分支合并到主分支。这允许代码审查、讨论以及在合并更改之前进行潜在的修改。这也是进行自动化检查的阶段,例如运行测试和静态分析,这使得拉取请求不仅是多人团队的有用工具,也对独立开发者有帮助。
要通过 GitHub 创建拉取请求,请按照以下步骤操作:
-
打开浏览器并导航到您的 GitHub 仓库。
-
单击您刚刚推送的分支旁边的比较与拉取请求按钮。
-
审查更改,并添加与 Jira 票据相关的任何额外信息或上下文。
-
指定适当的审阅者并点击创建拉取请求。
或者,如果你已经在 VS Code 中安装了 GitHub Pull Requests and Issues 扩展,你可以按以下方式在 VS Code IDE 中创建新的拉取请求:
-
按下Ctrl + Shift + P(Windows 或 Linux)或Cmd + Shift + P(macOS)打开 VS Code 命令面板。
-
输入
Github: Create Pull Request并从出现的列表中选择该选项。 -
为拉取请求选择基础分支和比较分支。
-
输入拉取请求的标题和描述。
-
审查你的更改并进行必要的调整。
-
点击创建拉取请求按钮提交你的拉取请求。
处理反馈并更新拉取请求
在审查过程中,通常会有反馈并要求对你的拉取请求进行更改。这是审查过程的正常部分,有助于通过尽早捕获更改来交付高质量的生产版本。幸运的是,处理这些更改与最初的 Git 提交一样简单——让我们看看需要的步骤:
-
如果在审查过程中要求更改,请在 VS Code 中进行必要的更新。
-
像最初提交更改时一样,提交并推送更改到功能分支。
-
拉取请求会自动更新你的新更改。
合并拉取请求
一旦我们达到了拉取请求被批准并且所有要求的更改都已完成的阶段,我们可以安全地将其合并到上游分支中,操作如下:
-
一旦拉取请求被批准,点击 GitHub 中的合并拉取请求按钮。
-
如果功能分支不再需要,请在 GitHub 或 VS Code 中删除它。
更新本地的主分支
现在我们需要做的就是刷新本地的主分支副本,确保我们有所有最新的更改,并且一切都已正确同步。以下步骤将帮助我们实现这一点:
-
在 VS Code 中,点击左下角的分支图标并选择main,切换回主分支。
-
像开始时一样拉取最新的更改。
我们现在已经完成了使用 SFDX 和 Git 开发 Salesforce 功能的典型生命周期。这代表了最基础的 DevOps 工作流——在许多团队中,这样的工作流可以保持简单。
在接下来的部分中,我们将查看 Salesforce 最常见的开发环境——沙盒和 Scratch org 之间的一些微妙差异,并了解每种环境的使用场景。
沙盒与 Scratch org
Scratch org 和 Salesforce 开发沙盒在提供开发和测试环境方面具有类似的目的;然而,它们在几个关键方面有所不同,我们将在这里讨论这些差异。
沙盒
Salesforce 沙盒是你 Salesforce 环境的副本,包括元数据和自定义内容。沙盒通常用于测试和开发目的,如创建和测试新功能、与其他系统集成或复制生产环境中的问题。开发人员可以使用沙盒测试新功能或自定义内容,而不会影响生产环境。沙盒也可以用于培训和用户验收测试(UAT),确保在部署前充分测试更改。此外,沙盒还可以用于集成测试、灾难恢复,并作为数据丢失或系统故障的备份。
Salesforce 沙盒用于开发和测试,提供四种不同类型的沙盒,每种沙盒具有不同的功能、目的、刷新周期和存储限制:
-
完整副本沙盒是你生产环境的完整复制,包括所有元数据和数据。它通常用于需要完整复制生产环境的测试和开发目的,如性能测试、**用户验收测试(UAT)**和培训。然而,你需要注意,这些沙盒每 29 天只能从生产环境刷新一次。完整副本沙盒也不支持源跟踪,因此不适合作为你的主要开发环境来使用 SFDX。
-
部分副本沙盒包括生产环境数据的子集,以及所有元数据。它通常用于需要比完整副本更小数据集的测试和开发目的,如功能开发或回归测试。此类型沙盒并非标准提供,而是 Salesforce 额外授权的付费项目。与完整副本沙盒不同,部分副本沙盒每五天就可以刷新一次,但像完整副本沙盒一样,它们不支持源跟踪。
-
开发者沙盒是专门为个人开发者或小团队提供的环境。它包括所有元数据,但没有数据。通常用于单个功能的开发或测试。大多数组织将拥有比完整副本或部分副本更多的开发者沙盒(通常每种沙盒限制为一个,除非你购买额外的沙盒)。它们可以每天刷新,但不会带来任何数据,并且具有更小的数据容量。
-
开发者专业版沙盒类似于开发者沙盒,但具有更大的存储容量。它通常用于更复杂的开发和测试任务,如集成或应用开发。
Scratch orgs(临时开发环境)
Scratch orgs 是一次性、临时的环境,可以快速创建和删除。它们主要用于敏捷开发,如在短时间内构建和测试新功能。
Scratch org 的生命周期本质上是临时的,最长为 30 天。这种短暂的特性鼓励开发者采用源驱动的开发方法,其中版本控制系统作为唯一的真实来源。相比之下,开发者沙箱是更持久的环境,可能存在较长时间,这使得开发者更容易无意中积累过时或未使用的代码和配置。
Scratch org 设计为轻量且可快速配置。通过调整 Scratch org 定义文件,它们可以根据特定项目的需求创建并定制所需的功能、设置和数据。这使得开发者可以轻松创建多个针对不同项目或任务定制的 Scratch org。另一方面,开发者沙箱是作为生产环境的副本创建的,包括所有自定义和部分数据,这使得它们的设置和配置较为繁琐且耗时。
默认情况下,当创建 Scratch org 时,它不会与生产 org 中启用的功能或元数据建立任何连接。它是根据一个通用模板创建的,包含一组基础功能。这意味着新创建的 Scratch org 不会反映生产 org 的特定特性或自定义设置,如果你正在开发和测试与这些特定设置或元数据相关的功能,可能会面临挑战。
为了克服这个问题,Salesforce 引入了定义文件的概念。定义文件是一个 JSON 文件,指定了 Scratch org 的形状或你希望 Scratch org 拥有的特性。它可以定义功能、设置和版本的偏好。例如,定义文件可能包含启用某些 Salesforce 功能的指令,如 Einstein Analytics 或个人账户。
手动创建定义文件使你可以根据生产环境定制 Scratch org。然而,手动创建一个与复杂的生产 org 完全匹配的定义文件可能会非常耗时,并且可能容易出错。
为了帮助解决这个问题,Salesforce 引入了 org 形状的概念。org 形状本质上是你生产 org 功能和设置的快照,你可以在创建 Scratch org 时将其用作模板。通过使用 org 形状,你可以快速而准确地在 Scratch org 中重建生产 org 的环境,而无需手动在定义文件中指定所有设置。
之前提到的短暂性、轻量化和可配置性的组合意味着,scratch org 更有利于支持持续集成和持续交付(CI/CD)流程。scratch org 的可丢弃性质使得开发者可以根据需要快速创建、测试和销毁环境,从而实现与 CI/CD 流水线的无缝集成。由于开发者沙箱的生命周期较长且设置更为复杂,它们可能不太适合这种自动化工作流。
总结
在本章中,我们回顾了使用 Salesforce 的标准堆栈和源代码控制工具的端到端生命周期。让我们回顾一下这个过程包括了哪些内容。
我们查看了如何将 Git 仓库初始化或克隆到本地机器,确保我们拥有最新的代码库版本。通过 VS Code,我们能够轻松访问和管理源代码,并在集成终端或 VS Code 内置的命令面板以及 Salesforce 扩展包中运行 SFDX 命令。
在开始开发过程之前,我们在 Git 仓库中创建了一个新的分支,以表示我们正在开发的特定功能或任务。这个分支通常根据关联的 Jira 工单命名,以保持可追溯性和组织性。一旦创建了特性分支,我们切换到该新分支,并开始实施所需的更改。
作为开发过程的一部分,我们利用 SFDX 工具来创建、检索和部署元数据组件。尽管我们在示例中使用了沙箱环境,但我们也可以利用 scratch org——临时的 Salesforce 环境——在最终确定代码之前对更改进行测试和迭代。在这个过程中,我们将更改提交到特性分支,并提供清晰简洁的提交信息,以维护全面的历史记录。
开发完成且更改经过充分测试后,我们将特性分支推送到远程 Git 仓库。这时,我们就可以创建拉取请求,将特性分支合并到主分支。拉取请求为团队成员提供了一个机会,审查更改、提供反馈并建议改进。它还作为一种质量保证措施,确保代码库保持稳定并维持所需的质量水平。
在获得团队批准后,我们可以通过拉取请求将特性分支合并到主分支。然后,主分支准备好进行部署到暂存环境或生产环境,以进行进一步的测试和验证。
一旦部署成功,特性分支可以在本地和远程仓库中删除,以保持干净和有序的代码库。
使用拉取请求、基于 Jira 工单的特性分支和协作评审过程,确保了在整个 Salesforce 开发生命周期中代码库的高质量、可追溯性和可维护性。
整个工作流程是通过免费工具实现的,并为 Salesforce DevOps 过程提供了最简单的入门点。随着需求的增长,自动化的力量变得更加重要,特别是在 CI/CD 的背景下。
我们将在第七章中更详细地讨论 CI/CD。在此之前,在下一章中,我们将通过探讨打包来采用另一种 Salesforce 变更管理的方法。
第六章:探索打包
有许多方法可以在不同环境之间传递 Salesforce 更改,同时遵循 DevOps 原则。使用 Salesforce 包是其中一种流行的机制,包可以是托管的、非托管的或解锁的包。
在本章中,我们将讨论这三种类型的 Salesforce 包,它们的使用场景以及相关注意事项:
-
非托管包 – 用于与其他组织或用户共享自定义或应用程序,但没有内建的版本控制或升级功能。
-
解锁包 – 旨在实现高效的应用生命周期管理、模块化开发和单一组织中的版本控制。它们也是在 Salesforce 平台上分发开源解决方案的流行方式。
-
托管包 – 旨在将基于 Salesforce 平台构建的自定义应用程序、扩展或集成分发给多个组织或客户,提供对构建代码的保护、版本控制和可升级性。
本章结束时,您不仅会清楚了解这些不同类型包之间的区别,还能明白何时使用它们以及如何在 Salesforce 中构建它们。
技术要求
对于非托管包、解锁包和 2GP 托管包,除了 Salesforce 环境外不应该有其他额外的要求——理想情况下是使用沙盒或开发者版。
对于 1GP 托管包,您在开发要分发的托管包时,需要一个独立的打包组织。打包组织是一个独立的 Salesforce 组织,用于开发、打包和分发托管包。
对于 Salesforce ISV 合作伙伴来说,通常会使用合作伙伴开发者版组织,它相较于普通开发者版组织,具有更多功能和更高的限制。这些包适用于 Salesforce 注册合作伙伴,而不是大多数 Salesforce 客户的日常使用。
用于测试包命令的示例项目可在与本书关联的 GitHub 仓库的 Chapter6 文件夹中找到。
非托管包
非托管包是 Salesforce 最初实现打包的一部分,因此也属于现在所称的第一代打包(1GP)。它们用于在不同组织或用户之间捆绑和共享自定义内容、应用程序或模板。非托管包提供了一种分发组件的方式,允许开发者在安装后根据需要进行修改或扩展。
由于未管理包是 1GP 的一部分,它们遵循的开发和打包流程很少是由源代码驱动的。这意味着包内的组件通常是从一个组织中选择的,而不是从版本控制系统中的分支选择的。未管理包缺乏源代码驱动的开发,这使得涉及版本控制、持续集成和持续部署的精简高效的 DevOps 流程变得困难。
这种方法的另一个限制是未管理包不支持包本身的版本控制或就地升级。对未管理包内组件的任何更新或更改都必须在安装后手动在目标组织中进行。这可能导致在长期管理和维护自定义功能时出现挑战,特别是在更大和更复杂的 Salesforce 实施中。
在未管理包中缺少特定于包的命名空间也意味着其组件会与目标组织的元数据合并,没有任何隔离。这可能导致命名冲突和部署时的潜在问题,使得管理依赖关系和维护目标组织中清晰的元数据结构变得更加困难。如果一个未管理包被安装到一个有命名空间的组织中,组件将继承该组织的命名空间。
如您所见,原始的 1GP 方法存在多个限制,这就是 Salesforce 将其替换为第二代打包(2GP)的原因,而这也是当前推荐的方法。
正如我们所讨论的,未管理包并不完全适合用作您的 DevOps 策略的一部分,因此让我们来看看解锁包,它是在 Salesforce 的 2GP 实施中引入的。
解锁包
Salesforce 解锁包是一种现代、灵活且模块化的打包解决方案,允许开发人员和管理员打包、部署和管理在 Salesforce 平台上构建的自定义功能和应用程序。它们是 Salesforce 源代码驱动开发方法的一部分,强调使用版本控制系统和持续集成管道来实现高效的开发和部署过程。
解锁包解决了在大规模和复杂的 Salesforce 实施中管理和部署自定义功能的挑战。通过将应用程序和自定义功能拆分为模块化单元,它们使团队能够更有效地管理和分发这些组件。这种模块化的方法促进了更好的协作、更容易的版本控制和精简的开发过程。解锁包面向那些希望利用最佳实践进行应用程序生命周期管理、精简部署过程并减少与元数据部署相关复杂性的开发人员和管理员。
与主要用于将应用程序分发到多个公司或客户的托管包不同,解锁包是为单一公司内部使用而设计的。它们尤其适用于拥有大规模 Salesforce 团队的企业,这些团队需要一种结构化且可维护的方式来管理和部署跨不同环境(如开发、测试和生产)的定制功能。通过提供一种可扩展且模块化的方法来进行 Salesforce 开发,解锁包帮助组织优化其 Salesforce 实施并推动更好的业务成果。
由于解锁包是一种基于源代码的方法进行打包,因此在创建它们时更依赖于使用命令行。你需要使用Salesforce DX(SFDX)方法来管理你的元数据,因此必须启用 Dev Hub。为此,请按照以下步骤操作:
-
登录到你的 Salesforce 组织。
-
点击右上角的齿轮图标并选择设置。
-
在
Dev Hub中选择并点击它。 -
将启用 Dev Hub切换为开启,并在同一页面启用解锁包。
启用此功能后,你就可以通过命令行与 Dev Hub 组织进行交互,无论是独立的还是 VS Code 中嵌入的终端。要创建新的解锁包,请运行以下命令:
sf package create --name MyPackageName –t Unlocked --path force-app -v MyDevHub
将MyPackageName替换为你的包名,将MyDevHub替换为你在 Dev Hub 组织认证时使用的别名。
此时,假设你已经有一个本地项目,并且已将代码提交到 Git。虽然源代码控制在创建包时不是必需的,但作为 DevOps 流程的一部分,现在正是确保 Git 仓库是最新的好时机,然后再创建新包。在本地项目中更新了元数据组件后,你可以使用以下命令创建新包:
sf package version create -p MyPackageName -d force-app -k MyPassword --wait 10 -v MyDevHub
将MyPackageName替换为你的包名,MyPassword替换为包的密码(可选),将MyDevHub替换为你在 Dev Hub 组织认证时使用的别名。
创建新包版本后,添加的元数据组件将包含在解锁包中。你可以使用以下命令在目标 Salesforce 组织中安装此包:
sf package install --package MyPackageName@1.0.0 -o MyTargetOrg -w 10
再次,你需要将MyPackageName@1.0.0替换为包名和版本,将MyTargetOrg替换为目标组织的用户名或别名。值得注意的是,如果在前一个版本创建时设置了密码,则必须在这里使用-k标志提供密码才能完成安装。
由于解锁包采用的是源驱动开发方法,而非基于组织的开发方法,因此它与整个过程中的 DevOps 使用更加契合。通过利用源代码控制,并将较大的代码库拆分成可以独立存在于不同 Git 仓库中的功能模块,你可以在使用解锁包进行交付时,更加灵活地调整方法。
然而,这种模块化的一个潜在问题是,有时会出现某些元数据同时属于多个包的情况。例如,如果你有两个独立的功能模块,它们都使用或依赖于 Opportunity 对象,你可能会遇到一个情况,即跨包的更改之间存在循环依赖关系。
解决这个问题的一种方法是拥有一个集中式的 core 包,其他包都引用它。在开发此包以外的新功能时,你需要确保在开发环境中安装了该核心包的最新版本。
更好的方法是,在解锁包开发中充分利用命名空间。命名空间应该是创建 Salesforce 解锁包的核心部分。它们确保唯一性——如果某人已经有一个名为 MyClass 的 Apex 类,你的 MyClass 不会与之冲突,从而避免了棘手的命名冲突。
命名空间还可以有效地进行包的版本管理。Salesforce 使用命名空间来管理包的多个版本,知道哪些版本是兼容的,以及如何处理升级或回滚。
此外,命名空间提供了另一种清晰分隔包代码的方式。它可以明确哪些组件属于特定包,将其代码与组织的其他元数据隔离开来。这有助于调试和维护。
在代码层面,而非在打包时,命名空间还带来了一些额外的好处。当第三方系统与你的包的 API 和组件进行集成时,命名空间消除了歧义。即使是在动态 SOQL 或 REST 调用中,引用也变得清晰,并且命名空间允许控制哪些组件是全局可访问的,哪些是私有的。可以设定公开使用的边界。
在创建包时,第一步是注册一个唯一的命名空间标识符。这将所有组件与该命名空间绑定。接下来,在构建新版本时,命名空间会包含在包的元数据中——在安装过程中,Salesforce 使用命名空间来分隔传入的组件,避免冲突。在代码和配置中,组件可以通过命名空间前缀来引用,例如 namespace__MyClass。
然而,命名空间也有一些缺点。它们将您锁定到一个永久的标识符,这个标识符之后无法轻松更改。引用命名空间组件会增加复杂性。迁移现有的未命名空间代码可能需要繁琐的调整。直观命名空间的可用性可能有限。跨多个命名空间包进行调试可能变得复杂。
总体来说,优点大于局限性,特别是在可管理性和版本控制方面。但重要的是要意识到这些缺点,并根据这些缺点来规划您的命名和开发。
幸运的是,Salesforce 也认识到这个挑战,并提供了另一种包类型来应对这种情况。让我们进一步探讨这些依赖于组织的包。
依赖于组织的包
Salesforce 提供的另一种解锁包类型——依赖于组织的包,通过推迟在安装时进行更改的编译和验证,解决了依赖问题。这意味着这些依赖项不一定需要存在于您的开发组织中或您的源控制中,您可以依赖目标组织中存在的元数据。
这种类型的解锁包非常适合大型、复杂并且已经使用了很长时间的 Salesforce 组织,因此积累了大量的更改。将这些更改拆解为独立模块是一项漫长且具有挑战性的工作,但通过拥有能够依赖目标组织中未打包元数据的包类型,您可以推迟(甚至避免)重新构建整个组织的需求。
创建一个依赖于组织的包也是非常简单的——命令与创建解锁包时相同,只需指定--orgdependent标志,如下例所示:
sf package create --name MyPackageName -t Unlocked --path force-app -v MyDevHub --org-dependent
您可能会想把所有的解锁包都做成依赖于组织的包,以便获得即时验证的优势,但依赖于组织的包也有一些关键的缺点,最终意味着您应该始终评估适合您用例的正确包类型:
| 特性 | 解锁包 | 依赖于组织的包 |
|---|---|---|
| 安装灵活性 | 您可以在任何组织中安装这些包,无论它们包含什么元数据。 | 您只能在包含包依赖的特定元数据的组织中安装这些包。 |
| 依赖 验证时间 | 在创建包版本时,包的依赖项会被检查。 | 在安装包到组织时,包的依赖项会被检查。 |
| 依赖于 其他包 | 这些包可以依赖于其他包。 | 这些包不能依赖于其他包。 |
| 依赖解析 | 在创建包之前,您需要解析所有的依赖关系。 | 在创建包之前,您无需解析任何依赖关系。 |
| 支持的 元数据类型 | 请参阅“元数据覆盖报告”的解锁打包通道,查看支持的元数据类型列表。 | 请参阅“元数据覆盖报告”的解锁打包通道,查看支持的元数据类型列表。 |
| 开发和 测试环境 | 使用 Scratch Org 来开发和测试你的解锁包。 | 使用包含依赖元数据的沙箱。你也可以在沙箱中启用源跟踪,以便开发你的组织依赖的解锁包。在将包安装到生产环境之前,在沙箱组织中测试包。 |
| 代码 覆盖要求 | 在你可以推广并发布包之前,必须确保你的 Apex 代码的代码覆盖率至少达到 75%。 | 这里没有代码覆盖率的计算要求,但你应该充分测试你的 Apex 代码。 |
表 6.1 – 解锁包和组织依赖包的比较
在下一节中,我们将讨论 Salesforce 中的最终打包类型:托管包。
托管包
Salesforce 托管包由 Salesforce 合作伙伴(也称为独立软件供应商(ISV))开发、打包并分发。这些包提供了一种扩展 Salesforce 功能的方式,通过添加新功能、流程或应用,而无需从头开始构建。托管包通过 Salesforce AppExchange 分发,AppExchange 是一个在线市场,提供 Salesforce 应用、组件和服务。AppExchange 允许开发者和合作伙伴发布他们的托管包,供 Salesforce 客户发现、评估并直接安装到他们的 Salesforce 环境中。
托管包通常可以根据特定的业务需求进行定制,同时保持包提供的核心功能,但可定制的程度会根据包内包含的元数据有所不同。Salesforce DX 开发者指南中有一节内容,讲解了托管包中可以或不能更改的部分,可以在developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/packaging_packageable_components.htm找到。
包提供者负责维护和升级包,确保其与最新的 Salesforce 版本和行业标准兼容。这减轻了使用该包的组织的负担,特别是当该组织使用的是安装包且没有进一步定制或更改包内的元数据时。
Salesforce 与 Java 或 C# 等其他开发平台的最大不同在于,它对开发者的向后兼容性和 API 稳定性有着强烈的强调。当你在 Salesforce 平台上构建应用时,你可以放心,依赖的核心 API 不会突然被弃用或意外更改。
对于像 Java 或 C# 这样的语言,核心库或方法可以通过通知的方式被弃用,提醒它们将在未来的版本中移除。这迫使你作为开发者,持续重构代码以保持更新。但 Salesforce 采取了非常不同的方式来管理升级,并确保客户满意。
一旦某个 Apex API 作为托管包的一部分在 Salesforce 上发布,其方法签名将被锁定。API 功能可能会随着时间的推移发生变化,甚至可能会抛出新的异常,但原始的方法和签名将保持不变。这可以防止开发者在安装依赖包的升级时,因而匆忙重构自己的自定义代码。
此外,托管包还需经过 Salesforce 的严格安全审查,以确保它们符合性能、数据保护和隐私等必要标准。这为使用这些包的组织提供了额外的信任保障。
通常,托管包的生命周期仅在审批和分发阶段有所不同。托管包是在 scratch orgs 中开发,并通过 Salesforce AppExchange 分发。参与该市场需要你作为 ISV 合作伙伴在 Salesforce 注册,并为你的包提供有效的商业案例。一旦获得批准,你就可以开始制作你的包。
以下是分发过程的典型流程:
-
开发
-
测试
-
打包
-
安全审查
-
AppExchange 列表
-
安装和配置
-
持续支持和升级
开发
包创建者使用 Salesforce 工具(如 Apex、Visualforce、Lightning 组件等)开发托管包,确保与 Salesforce 的兼容性。
测试
与 Salesforce 的任何其他开发工作一样,包的元数据和代码应该经过充分的测试,不仅要确保其功能完整,还要符合 ISV 合作伙伴应遵守的严格安全要求。
Salesforce 提供了多个工具,帮助开发者引导完成这一过程,例如 Salesforce 代码分析器。该工具利用 Salesforce 图形引擎深入分析代码,跟踪依赖关系,查找常见的安全问题,特别是记录访问相关的问题,采用一种叫做数据流分析(DFA)的技术。DFA 是一种帮助你更好理解复杂计算机代码的方法。它通过一次性查看整个代码,弄清楚代码的工作原理。它通过分解代码的步骤来实现这一点,包括评估条件、创建类、调用方法和静态调用等内容。它还会尝试在每一步中猜测变量和字段的值。这一切都有助于更好地了解代码的工作方式。
分析器还利用其他开源分析引擎,如 PMD 和 ESLint,来完善这些检查的覆盖范围。
打包。
历史上,受管包遵循一个较长的过程,类似于之前讨论的 1GP,这包括以下内容:
-
选择要包括的组件,如 Apex 类、Visualforce 页面、Lightning 组件、自定义对象等。
-
设置包的属性,例如包名、命名空间、版本号和描述。
-
如果有的话,定义对其他包或 Salesforce 特性的依赖关系。
-
将包指定为受管包,以确保版本管理、可升级性和知识产权保护。
然后,可以将该包上传到 Salesforce 环境中,生成安装 URL 以供分发。
随着 2GP 的出现,这一过程变得更加简化。首先,确保你的包所需的所有组件都在项目目录中(通常位于 force-app 文件夹内)。该项目应与相应的 Scratch Org 相关联,并且在 sfdx-project.json 文件中指定所需的命名空间。
创建实际包的过程比旧的 1GP 方法更直接,与解锁包的区别仅在于一个简单的命令行参数,-t Managed,如下所示:
sf force package create –n "My Managed Package" -t Managed –r force-app
安全审查。
在受管包能够在 AppExchange 上列出之前,它必须经过安全审查过程。该过程包括以下内容:
-
对包的代码和组件进行全面评估,以识别潜在的安全漏洞,如注入攻击、敏感数据的非安全存储和不当的访问控制。
-
确保包符合 Salesforce 的安全指南、最佳实践和合规要求。
-
向 Salesforce 提交安全审查请求,并提供相关文档和测试用例。
-
解决 Salesforce 在审查过程中识别的任何安全问题,并重新提交包以供审批。
一旦包通过安全审查,它将获得通过安全审查的状态,向客户表明它符合 Salesforce 的安全标准。
AppExchange 列表。
安全审查通过后,该包可以在 Salesforce AppExchange 上列出。列出包的过程包括以下步骤:
-
创建一个包含包的基本信息的 AppExchange 列表,如名称、描述、功能、定价和支持详情。
-
添加屏幕截图、视频或其他媒体,展示包的功能和优势。
-
使用在打包过程中生成的安装 URL,将该列表与受管包关联起来。
-
向 Salesforce 提交列表进行审批,Salesforce 将审查其质量、品牌和内容指南。
一旦列表获得批准,它将在 AppExchange 上公开发布,允许客户发现并评估该包。
安装与配置
Salesforce 客户可以通过以下步骤在 AppExchange 中查找、评估并安装托管包:
-
浏览 AppExchange,使用搜索、筛选器和分类来发现满足特定需求的包
-
通过查看包的描述、功能、定价、客户评价以及任何可用的演示或试用来评估该包
-
通过点击 AppExchange 列表中的 立即获取 按钮来安装包,启动客户 Salesforce 环境中的安装过程
-
在安装过程中授予访问权限并设置包的安全设置,确保其与组织的安全政策一致
-
安装后通过定制设置、调整布局或设置任何必需的集成来配置包
一旦安装并配置完成,托管包就会成为客户 Salesforce 环境的一个重要组成部分,扩展平台的功能以满足他们的特定需求和要求。
持续支持和升级
安装并配置完包后,包提供商负责提供持续的支持和更新。这确保了该包与最新的 Salesforce 版本、行业标准和客户期望保持兼容。持续的支持和升级过程通常包括以下内容:
-
通过支持渠道(如电子邮件、电话或在线论坛)监控并处理客户反馈、问题和疑问。
-
定期发布包更新,以修复 bug、增强功能并添加新功能。这些更新作为新包版本发布,客户可以根据自己的需要选择安装。
-
确保与最新的 Salesforce 版本兼容,进行必要的调整以保持与平台的无缝集成。
-
跟进行业趋势、客户需求和技术进展,确保包对客户仍然具有相关性和价值。
-
通过通讯渠道(如新闻通讯、网络研讨会或应用内通知)向客户告知重要更新、新功能和最佳实践。
包提供商提供的持续支持和升级有助于包的长期成功、客户满意度和整体价值。
打包模型的优缺点
打包作为 DevOps 过程中开发更新的分发方式,符合源驱动的软件开发原则。由于不同类型的包提供了不同的使用场景和优势,选择最合适的交付模型对于优化 DevOps 生命周期中的工作流程至关重要。
让我们回顾一下差异:
| 包类型 | 优点 | 缺点 | 主要用途 |
|---|---|---|---|
| 非托管 | 易于定制 | 无版本控制 | 用于学习目的的代码和配置共享 |
| 允许进行代码编辑 | 无自动升级 | 共享示例解决方案 | |
| 无命名空间要求 | 由于可编辑代码存在安全隐患 | 协作开发 | |
| 不支持托管包功能 | 可供专业服务团队使用,其中有一些常见的定制化需求,许多客户都需要,但每个客户可能需要进行少许调整 | ||
| 解锁 | 易于定制 | 无自动升级 | 在多个组织之间部署可重用组件 |
| 版本控制 | 手动升级过程 | 共享模块化解决方案 | |
| 允许进行代码编辑 | 由于可编辑代码存在安全隐患 | 促进内部协作和开发 | |
| 支持托管包功能(例如,命名空间) | 需要 Salesforce DX 和源驱动开发 | ||
| 托管 | 自动升级 | 定制化有限 | 商业应用分发 |
| 版本控制 | 代码不可编辑 | 在 AppExchange 上分发应用程序 | |
| 由于代码不可编辑增强了安全性 | 需要命名空间 | 保护知识产权 | |
| 支持托管包功能(例如,命名空间) | 2GP 要求 Salesforce DX 和源驱动开发(尽管 1GP 仍可在没有 DX 模式的情况下完成) |
表 6.2 – 每种包类型的优缺点
拆分现有的单体应用程序
将一个成熟的单体应用程序迁移到 Salesforce 的包开发模型可能是一项重大的工作,充满了复杂性和挑战。
在复杂性方面,通常需要对代码进行重构,以打破紧耦合并将组件适配到模块化包中。依赖管理变得至关重要,以解开相互关联的组件。引入命名空间可能会增加更新所有引用的复杂性。数据模型可能需要重新设计,以适应新的包化架构。权限集和配置文件可能需要重新定义。自动化和 CI/CD 流水线需要适应以处理打包、版本控制和依赖关系。保持各个组织环境与正确的包版本同步非常复杂。
就挑战而言,转型将需要大量的资源和时间投入。随着团队学习新模型,知识差距会产生。测试策略需要彻底改革,可能包括重写测试和脚本,并设置新的测试环境。保持向后兼容性可能会限制变更,迫使需要对旧系统进行支持。一旦转型完成,跨包和客户的版本管理将增加复杂性。习惯于快速部署的利益相关者可能会抵制更慢、更受控制的包生命周期。除了人员成本外,培训、停机时间和工具等费用将逐渐累积。
为了顺利过渡,分阶段的逐步方法可以提供帮助。广泛的培训和专家咨询将培养必要的技能。详细的文档提供了知识库。反馈渠道让问题早期显现。风险评估和回滚计划可以规避陷阱。合理的资源分配,无论是人力还是计算资源,奠定了基础。
虽然困难,将单体应用程序迁移到包模型最终可以实现模块化、可扩展的开发和更容易的维护。通过仔细的规划和执行,长期的好处可能会超过达到目标的复杂性。
总结
在本章中,我们探讨了将代码更改打包作为部署技术,并比较了不同类型的包。对于每种类型的包,我们已经看到了将 Salesforce 更改捆绑成这些包以便进一步分发的步骤。
我们还看到,如果选择适当类型的包,这些更改可以遵循源驱动的 DevOps 流程。打包绝不是替代 DevOps 流程的手段;相反,它是 Salesforce 平台上 DevOps 的一部分技术。同样,它也不是在 ISV 合作伙伴空间以外的场景中交付更改的唯一方式。
在下一章中,我们将开始探讨如何将源驱动工作流的所有元素结合起来,并在我们研究 CI/CD 自动化流程时加入一些自动化。这代表了一种不需要打包的替代交付机制。
第七章:CI/CD 自动化
在本章中,我们将学习如何利用 持续集成和持续交付 (CI/CD) 自动化我们的 DevOps 流程。我们还将介绍一些流行的工具来实现这一目标。
利用 CI/CD 的力量,我们可以为 Salesforce 的开发和运维创建更高效、可靠和流畅的工作流。这种方法使我们能够快速响应变更,降低部署失败的风险,最终帮助我们交付更高质量的软件。
我们将涵盖以下主要主题。
-
CI/CD 管道简介:首先,我们将定义 CI/CD,解释其优点,并讨论它如何适用于 DevOps 策略。我们还将强调在实施 CI/CD 时应遵循的关键原则和最佳实践。
-
GitHub Actions:本节将重点介绍 GitHub Actions,这是一个灵活且强大的 CI/CD 工具,可以直接与您的 GitHub 仓库集成。我们将探讨如何设置工作流程,自动化测试以及处理部署,所有这些都在 GitHub 平台内完成。
-
Jenkins:Jenkins 是 CI/CD 社区中广受欢迎的工具,我们将深入探讨它。我们将展示如何为 Salesforce 项目配置 Jenkins,创建流水线,并利用其广泛的插件生态系统。
-
Salesforce 特定工具:Salesforce 提供了几个工具,可以帮助 CI/CD,例如 Salesforce DX (SFDX) 和 Salesforce CLI。我们将讨论如何利用这些工具来简化您的 CI/CD 流程并解决 Salesforce 特定的挑战。
-
CI/CD 管道的实际应用:最后,我们将查看新建的 CI/CD 管道作为强大 DevOps 实施的优势。
通过本章末尾,您应该对 CI/CD 在 Salesforce DevOps 中的角色有了扎实的理解,了解了实施它的可用工具以及开始自动化您自己流程的步骤。
技术要求
对于 Jenkins,您需要一个能够托管 Jenkins 软件的服务器。这可以是物理服务器、虚拟机或基于云的服务器。具体的要求将取决于项目的规模,但至少应规划至少 1 GB 内存、50 GB 硬盘空间和一台现代 CPU。值得注意的是,出于学习目的,您可以在本地开发机上运行 Jenkins,如果您想跟随本书中的过程和步骤进行,但是对于实际的 DevOps 工具链使用,建议使用专用的托管解决方案。
SFDX 和 Salesforce CLI 是 Salesforce DevOps 的关键工具。要使用它们,您需要在系统上安装 Salesforce CLI。如果您尚未完成安装,可以重新查看 第五章,详细介绍了设置过程。
要在 Salesforce 中实施 CI/CD,您需要一个有效的 Salesforce 开发者账户。如果您与团队一起工作,您还需要一个 SFDX “hub” 组织,在其中创建和管理 scratch org。
CI/CD 的一个关键部分是版本控制。GitHub 是最广泛使用的平台,并且由于与 CI/CD 工具的出色集成,推荐使用它。您需要一个 GitHub 账户以及一个用于存储 Salesforce 代码的仓库。
本章的源代码可在 github.com/PacktPublishing/Salesforce-DevOps-for-Architects/tree/main/Chapter7 上获取。
引入 CI/CD
软件开发的世界多年来发生了显著变化,越来越注重敏捷性、效率和质量。在这种背景下,CI 和 CD 成为了推动开发工作流程显著改进的关键实践。在本节中,我们将探讨 CI/CD 的核心概念、它们的好处以及它们在 DevOps 策略中的作用。
持续集成(CI)
CI 是一种开发者将代码频繁提交到共享仓库的过程。每次提交都可以经过自动化构建和测试周期,以便在开发生命周期的早期阶段识别问题。这个 CI 过程有助于减少集成问题,并使开发团队能够及时反馈任何问题。
持续交付(CD)
CD 将 CI 的理念进一步拓展。它将软件发布过程自动化,直到准备好生产环境,但稍微缺少实际的生产部署。这一实践确保了存储库中的代码和配置(通常是主分支或 master 分支)始终处于生产就绪状态,减少了部署的风险和工作量,并使团队能够更快、更频繁地向客户交付更新和改进。经过自动化测试后,软件已准备好部署,但仍需要人工决策来确定何时部署到生产环境。
CI 和 CD 一起构成了现代 DevOps 实践的基础。它们促进了协作文化、快速反馈周期,并专注于高质量的输出。实施 CI/CD 可以带来更高效的开发流程,减少生产环境中出现的 bug,并为用户提供更好的产品。
在 Salesforce 环境中,CI/CD 可以带来额外的好处。Salesforce 项目通常涉及多个开发者在复杂系统的多个方面进行工作。通过 CI/CD,您可以确保变更频繁地集成和测试,从而减少冲突和错误的风险。同时,自动化部署可以简化将变更推送到测试、预发布和生产环境的过程。
然而,值得注意的是,实现 CI/CD 不仅仅是使用某些工具或遵循特定步骤的问题。它是一种文化转变,需要整个团队的认同,专注于自动化和测试,以及持续改进流程的承诺。这可能涉及改进现有的测试实践,或者解决技术债务和糟糕的架构——这些都是正确实施 CI/CD 的先决条件。虽然这些变化可能看起来令人生畏,但采用 CI/CD 的好处通常超过所需的努力。在接下来的部分中,我们将深入探讨可以帮助您将 CI/CD 的好处带入 Salesforce 项目的具体工具和实践。尽管最初的努力可能很大,但从改进的自动化、测试和交付流程中获得的回报是值得的。只要团队承诺并专注于持续改进,CI/CD 可以改变您在 Salesforce 上构建和交付的方式。
CI/CD 流水线
在 CI/CD 的领域中,一个关键的概念是流水线。CI/CD 流水线是一系列步骤,您的更改(无论是代码、元数据还是数据)将通过这些步骤,从开发到生产环境。它自动化了代码更改的集成过程、通过测试验证这些更改,并将它们交付给最终用户。通常,它被可视化为一系列阶段,每个阶段都有特定的目的。当引入更改时(例如,当开发者将代码推送到仓库时),它会触发流水线,改变会通过各个阶段。让我们来看看一些典型的流水线阶段:
-
构建阶段:这是代码被编译、依赖项被获取并且软件被打包部署的地方。在 Salesforce 项目中,这可能包括创建一个新的 SFDX scratch org,将代码推送到该组织,并运行所需的脚本。
-
测试阶段:自动化测试会针对构建运行,以确保它的行为符合预期。这可能包括单元测试、集成测试和功能测试。在 Salesforce 的上下文中,这必须包括运行 Apex 测试,并可能测试其他组件,如 Visualforce 页面或 Lightning 组件。
-
部署阶段:如果构建通过了所有测试,它可以被部署到一个预发布环境中进行进一步测试,如果在那里也通过了测试,它就可以被部署到生产环境中。像 SFDX 和变更集这样的 Salesforce 特定工具可以用于这些部署。最终,这些工具是对元数据 API 的封装,而元数据 API 仍然是部署更改的唯一底层方式。
-
监控阶段:部署后,应用程序会被监控,以确保它在生产环境中正常运行。任何出现的问题都可以反馈到开发过程中。
这些阶段中的每个通常都是自动化的,这意味着在所有检查通过的前提下,变更可以从一个阶段推进到下一个阶段,而无需人工干预。自动化是 CI/CD 流水线的一大优势,因为它减少了人为错误的风险,加快了交付过程,并为开发团队提供了快速反馈。
每个阶段都旨在捕捉不同类型的问题。例如,构建阶段可能会捕捉到语法错误,而测试阶段可能会捕捉到功能性错误,监控阶段则可以识别性能问题或实时环境中的错误。使用像 PMD 这样的静态代码分析工具,或者其他代码检查工具,如针对 Lightning Web Components 的 ESLint,可以增强整个开发团队的一致性代码风格和最佳实践。通过将规则编码到这些工具中,开发人员如果违反了规范,就能得到即时反馈。这有助于推动可读、可维护的代码,当然也可以添加到流水线中自动运行。
在 Salesforce 的背景下,CI/CD 流水线可以帮助管理在多租户、元数据驱动环境中开发的复杂性。它允许团队以受控、可重复的方式开发、测试和部署变更,从而减少手动部署相关的风险,并确保高质量的输出。在接下来的章节中,我们将讨论如何使用流行的工具(如 GitHub Actions 和 Jenkins)来实现这样的流水线。
GitHub Actions
在我们进入 CI/CD 领域的过程中,我们会遇到许多有助于促进这些实践的工具。其中一个工具以其简单性和与 GitHub 平台的紧密集成而脱颖而出,那就是 GitHub Actions。这个强大的自动化工具允许你直接在 GitHub 仓库中创建自定义的软件开发生命周期(SDLC)工作流。
GitHub Actions 使你能够在自己的代码库中自动化、定制和执行软件开发工作流。你可以在存储代码和协作项目的同一个地方部署工作流。这意味着开发周期更快、更简化,因为你可以在 GitHub 项目内部管理 CI/CD,而无需依赖外部工具。
在 GitHub Actions 中,工作流、任务和操作具有层级关系,这允许你组织和结构化你的 CI/CD 过程。这个层级关系具有以下几个级别:
-
.github/workflows目录包含定义工作流的.yml或.yaml文件。 -
runs-on指令。单个工作流可以执行多个任务,默认情况下这些任务并行执行,尽管你可以将它们调整为顺序执行。每个任务由多个步骤组成,每个步骤执行特定任务。这些任务可以使用相同的运行器,也可以使用不同的运行器。 -
步骤:步骤表示作业中最细粒度的工作。每个步骤负责执行一个单一的命令或 Action。它们可以执行命令,这些命令是任何 shell 命令,也可以执行 Action,Action 是可重用的代码块。这些 Action 可以是由你开发的,也可以是 GitHub 开发的,或者是从社区的公共仓库中获取的。
图 7.1 – 工作流、作业和步骤之间的层次关系
作业中的一步可以是一个在 shell 中运行的命令,或者是一个 Action。在下面的示例中,作业中的每一步要么运行 shell 命令(例如 npm install sfdx-cli --global),要么使用 Action(例如 actions/checkout@v2)。
GitHub Actions 提供的不仅仅是建立 CI/CD 流水线的能力,它还允许自动化广泛的任务,如问题分诊和软件包发布。这使得它成为任何开发者工具包中不可或缺的多功能工具。
对于 Salesforce 开发者和架构师来说,可以通过 GitHub Actions 自动化任务,例如运行 Apex 测试、将代码部署到 Scratch org,以及将更改推广到暂存和生产环境。接下来的部分,我们将深入探讨如何设置和使用 GitHub Actions 来实现 Salesforce CI/CD。
GitHub 工作流实例
让我们先来看一个实际的 Git 工作流示例,然后逐步分析它在做什么。考虑下面这个 GitHub 工作流:
name: Salesforce CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
该 GitHub 工作流会在主分支上发生推送或拉取请求事件时启动。接下来,我们需要在工作流中定义一个或多个作业:
jobs:
deploy:
runs-on: ubuntu-latest
在这个实例中,我们定义了一个名为 deploy 的作业,它将在 ubuntu-latest 环境中执行。GitHub Actions 工作流中的 runs-on: 字段配置作业将运行的机器类型。该字段可以具有多种值,进而确定执行作业所使用的 Runner 类型。
Runner 是一台配备了 GitHub Actions Runner 应用程序的服务器,负责执行任务。ubuntu-latest 值表示任务应在 GitHub 托管的最新稳定版 Ubuntu 虚拟机上运行。
接下来,我们将定义作业应执行的步骤。首先,我们通过检出仓库中的代码并安装 Salesforce CLI 来进行一些准备工作,以便使用代码执行后续步骤:
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Salesforce CLI
run: |
wget https://developer.salesforce.com/media/salesforce-cli/sfdx/channels/stable/sfdx-linux-x64.tar.xz
mkdir ~/sfdx
tar xJf sfdx-linux-x64.tar.xz -C ~/sfdx --strip-components 1
echo "$HOME/sfdx/bin" >> $GITHUB_PATH
~/sfdx/bin/sfdx version
第一步使用 actions/checkout@v2 来检出当前仓库的源代码。通过 GitHub Actions,可以使用包含在你自己仓库中的 Action,公共仓库中的 Action,或者在 GitHub 自有发布镜像中的 Docker 容器镜像中的 Action。uses: 关键字用于在 GitHub Actions 工作流中指定这些 Actions。
在这种情况下,actions/checkout@v2 是指来自 actions 仓库的 checkout 动作,v2 是你想要使用的版本标签。这个 checkout 动作会将你的仓库检出到 $GITHUB_WORKSPACE 下,以便工作流可以访问它。
通过指定 v2,你指示工作流使用 checkout 动作的第二个主要版本。与之前的版本(v1)相比,这个版本可能包含新功能、变更或 bug 修复。动作的维护者根据语义版本控制规则定义这些版本。
最佳实践是指定一个版本(而不是使用默认的分支,通常是 main 或 master),以保护你的工作流免受这些分支中可能引入的破坏性变更。
第二步是全局安装 Salesforce CLI。Salesforce CLI 用于与你的 Salesforce 组织进行身份验证并运行 Apex 单元测试。然而,Salesforce CLI 并没有预装在 GitHub 的虚拟环境中,因此你需要在工作流中安装它。
Salesforce CLI 有两种主要的分发方式——作为二进制可执行文件和作为通过 npm 安装的 Node.js 包。我们在脚本中选择使用二进制分发,因为 npm 安装在尝试添加额外插件时可能会遇到权限问题。npm 包需要 Node.js,并且需要全局安装,这通常需要 sudo 权限。使用 sudo 可能会导致文件系统权限问题。二进制分发避免了这些问题,这也是我们选择这种方法的原因。Node.js 的 npm 包也可以使用,但我们避免了它,因为在添加插件时可能会遇到权限问题。现在,我们可以进入下一个步骤:
# The URL is stored in the Github Secret named DEVHUB_SFDX_URL
# so here we store the URL into a text file
- name: 'Populate auth file with SFDX_URL secret of integration org'
shell: bash
run: |
echo ${{ secrets.DEVHUB_SFDX_URL}} > ./DEVHUB_SFDX_URL.txt
在前面的步骤中,我们利用了 GitHub 的每个仓库密钥来检索存储的值,并将该值复制到一个临时文件中,仅在此作业的生命周期内有效。该文件包含一个 SFDX 授权 URL,允许作业轻松连接到我们的 Salesforce Developer Hub 组织。
有三种方法可以创建这个身份验证文件。最简单的方法是将 sf org display --verbose --json 命令的输出重定向到一个文件中。例如,假设你正在使用一个已经授权的组织:
sf org display -o <OrgUsername> --verbose --json > authFile.json
在生成的 JSON 文件中,你可以找到存储在 sfdxAuthUrl 属性中的 URL,该属性位于 results 对象内。请注意,force:org:display --verbose 命令只会显示使用 Web 服务器流授权的组织的刷新令牌,而不会显示使用 JWT 承载流授权的组织。
此外,你还有选择生成一个 JSON 文件,其中包含一个名为 sfdxAuthUrl 的顶级属性,该属性包含身份验证 URL。或者,你可以创建一个纯文本文件,只包含 URL,而不包含任何其他内容。
SFDX 授权 URL 的格式如下:
force://<clientId>:<clientSecret>:<refreshToken>@<instanceUrl>
URL 使用 force:// 而不是 http:// 或 https://,并且 instanceUrl 不包含 https://,它只是域名。
下一步使用新创建的文件对 Salesforce 组织进行认证,该文件包含授权 URL,并为其指定别名 HubOrg:
- name: Authenticate to Salesforce
run: |
sf auth sfdxurl store -f DEVHUB_SFDX_URL.txt -a HubOrg
在认证我们的 Dev Hub 后,我们现在可以自动生成一个新的临时组织以供测试使用,并将代码传输到其中:
- name: Create A New Scratch Org
run: |
sf org create scratch --target-dev-hub HubOrg --set-default --definition-file config/project-scratch-def.json --alias ciorg --wait=10
- name: Push changes to new Scratch Org
run: |
sf project deploy start --target-org ciorg
有了这个新的临时组织,并使用 ciorg 别名,我们可以执行我们的 Apex 测试:
- name: Run all Apex tests
run: |
sf apex run test -o ciorg -l RunLocalTests -r tap -d test-results
最后,当我们完成时,会删除临时组织。这是一个重要步骤,因为 Salesforce 对每个 Dev Hub 中可以拥有的活动临时组织数量有严格限制:
- name: Delete scratch org
run: |
sf org delete scratch --target-org ciorg --no-prompt
每个工作中的步骤都在其独特的上下文中运行。然而,使用 GitHub 工作流语法,这些独立的步骤可以协调互动并相互配合。工作流配置提供了建立步骤之间依赖关系的能力,例如指定一个步骤必须等待另一个步骤成功完成后才能开始。它还允许一个步骤利用另一个步骤的输出,及其他交互。这种灵活的配置使得可以从一系列独立步骤构建复杂的自动化过程。
GitHub Actions 提供了一个多功能平台,便于在使用 SFDX 时定制你的 CI/CD 管道。凭借其执行各种任务的能力,从执行 shell 命令到运行脚本甚至是第三方软件,GitHub Actions 可以根据你的特定需求进行独特定制。
这种适应性同样适用于 SFDX,在其中你可以利用 GitHub Actions 来自动化多个任务。这些任务可以包括执行单元测试、将代码部署到不同的环境,甚至监督数据迁移。通过利用 GitHub Actions 的强大功能,你可以创建一个高效、可靠的自动化 CI/CD 管道,增强 SFDX 项目的开发和部署过程。
虽然前面的步骤为你提供了一个使用 GitHub Actions 进行 Salesforce CI/CD 的基本自动化工作流,但你可以通过更多的自动化测试、静态代码分析、审批流程等来扩展它。在 docs.github.com/en/actions/learn-github-actions 的官方 GitHub Actions 文档中,你可以找到大量的文档和教程。
如果你想尝试不同的 CI/CD 方法,可以考虑 Jenkins。它拥有大量的插件,支持自托管,可以让你更好地控制实现过程,并且具有更加直观的用户界面来设置和管理你的管道。在接下来的章节中,我们将更详细地介绍 Jenkins。
Jenkins
Jenkins 是一个开源自动化服务器,已经稳固地成为 DevOps 社区中不可或缺的工具。由于其丰富的功能集、插件生态系统以及高度的灵活性和控制能力,Jenkins 成为许多组织的首选。
Jenkins 被设计用来管理各种 DevOps 活动和流程,从简单的 CI 服务器到全面的 CD 中心,可以容纳任何类型的项目,无论其规模或复杂性。它允许你自动化交付管道的不同阶段,为项目团队提供关于项目健康状况的持续反馈。
Jenkins 的一个重要优势是它通过插件的可扩展性。在更新中心有超过 1,000 个插件,Jenkins 可以与几乎所有 CI/CD 工具链中的工具进行集成。你可以使用它来构建、测试并交付任何语言的代码,部署到任何平台。这种可扩展性使得 Jenkins 成为一个多功能工具,可以适应各种项目需求。
Jenkins 使用分布式架构,能够随着需求的增长轻松扩展。你可以设置 Jenkins,将工作分配到多台机器上,从而加速项目的构建、测试和部署。这种分布式特性对于大型和复杂的项目特别有利。
与 GitHub Actions 类似,Jenkins 可以配置来处理任务,例如运行 Apex 测试、创建和管理 SFDX scratch org、以及将元数据部署到各种 Salesforce 环境中。Jenkins 还可以与版本控制系统(如 Git)集成,增强其在 Salesforce CI/CD 管道中的功能。
设置 Salesforce 的 Jenkins CI/CD 管道的第一部分是安装 Jenkins 本身。根据操作系统的不同,这个过程会有所不同。Jenkins 是一个基于 Java 的应用程序,因此它可以在任何支持 Java 的平台上运行。在开始任何新的安装之前,建议始终确保系统的所有软件包都是最新的。
如果你使用的是 Ubuntu Linux,首先需要通过终端运行 apt update 和 apt upgrade 命令来更新系统软件包。然后,你需要安装 Java,因为 Jenkins 需要它才能运行。OpenJDK 包是一个不错的选择,可以通过 apt install openjdk-17-jdk 命令进行安装。在撰写本文时,JDK 20 是 Java SE 平台的最新版本。然而,JDK 17 LTS 作为 Java SE 平台的最新长期支持(LTS)版本,仍然是最为推荐的版本。
接下来,你应该将 Jenkins 仓库添加到你的源列表中,这是安装 Jenkins 的前提条件。你可以通过使用 wget 命令获取 Jenkins 仓库的密钥并将其添加到系统的软件仓库列表中。此密钥用于身份验证,并确保你系统上安装的软件包来自受信任的来源。你可以使用以下 wget 命令从 Jenkins 服务器直接下载 Jenkins 仓库密钥:
wget -q -O - https://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add –
-q 选项告诉 wget 安静地运行,这意味着它不会输出进度信息。-O - 选项则告诉它将下载的内容写入标准输出,表示为 -。然后,使用 | 符号将这些内容传递到 sudo apt-key add - 命令中,该命令将密钥添加到系统的受信任密钥列表中。
接下来,你需要将 Jenkins 仓库添加到系统的软件仓库列表中。这是通过将 Jenkins 仓库 URL 附加到存储在 /etc/apt/sources.list.d/ 目录中的仓库列表来完成的。你可以使用以下命令来执行此操作:
echo deb http://pkg.jenkins.io/debian-stable binary/ | sudo tee /etc/apt/sources.list.d/jenkins.list
echo 命令打印其参数,在本例中是 Jenkins 仓库的 URL 和要使用的软件包类型(binary)。此输出会被传递给 sudo tee 命令。tee 命令用于将接收到的输入附加到文件中,本例中是将输入追加到 /etc/apt/sources.list.d/ 目录中的 jenkins.list 文件。
一旦这些命令执行完毕,你的系统包管理器就设置好了,能够安装 Jenkins 并保持其更新。接下来的步骤是通过 sudo apt update 更新软件包列表,然后你可以继续通过 sudo apt install jenkins 安装 Jenkins。
对于 macOS 用户,首先需要安装 Homebrew,这是一个简化 macOS 上软件安装的包管理工具。安装 Homebrew 后,你可以使用它来安装 OpenJDK,然后再安装 Jenkins。和 Ubuntu 一样,安装 Jenkins 后,你应该启动 Jenkins 服务,并确保它在系统启动时自动启动。
在 Windows 上,过程略有不同。你需要直接从 Jenkins 网站下载 Jenkins WAR 文件,并从 Oracle 网站安装最新版本的 JDK。设置好 JAVA_HOME 环境变量后,你可以通过进入存放 Jenkins WAR 文件的目录,使用 java -jar 命令来运行 Jenkins。
在这三种情况下,一旦 Jenkins 启动,你可以通过在 web 浏览器中访问 http://localhost:8080 来进入 Jenkins 仪表盘。接下来会引导你完成其余的设置过程,包括创建管理员用户和配置安全设置。
在安装并启动 Jenkins 后,您需要为 SFDX 做好准备。SFDX 包含一套旨在增强和简化开发与部署过程各个阶段的工具。它需要 Salesforce CLI,因此您需要在与 Jenkins 相同的机器上安装它。如果您需要提醒,之前在 第五章 中已经介绍过 Salesforce CLI 的安装过程。
Salesforce CLI 安装完成后,您需要确保 Jenkins 可以与其交互。通过在 Jenkins 系统配置设置中添加 Salesforce CLI 的路径来完成此操作。您可以通过 Jenkins 仪表板上的 Manage Jenkins | Configure System 菜单导航到这些设置。
Jenkins 通过使用插件来完成特定任务和集成。对于 SFDX,您需要安装的关键插件包括 Pipeline 插件、Git 插件,以及根据您选择的版本控制解决方案,可能需要 GitHub 插件、Bitbucket 插件,或者任何可能与您的 Git 提供商相关的插件。在这个例子中,我们将专注于 GitHub 选项。Pipeline 插件使得在 Jenkins 中创建 CD 管道成为可能,而 Git 和 GitHub 插件使 Jenkins 能够与 Git 仓库进行交互。
这些插件可以通过 Jenkins 仪表板中的 Manage Plugins 菜单安装。安装后,Jenkins 将能够与 SFDX 交互,并从 GitHub 仓库拉取代码,为您的 CI/CD 管道奠定基础。
通过插件添加的 Git 支持使 Jenkins 能够监控 Git 仓库的更改,发生更改时拉取这些更改,并根据这些更改采取某些行动。Jenkins 通过使用 Webhooks 和轮询来实现这一点。Webhooks 是当更改发生时从 GitHub 发送到 Jenkins 的触发器,而轮询则意味着 Jenkins 会定期询问 GitHub 是否有更改。
要设置 webhook,您需要导航到 GitHub 上的仓库,进入 /github-webhook/ (例如,your-jenkins-url/github-webhook/)。确保选择了 application/json 和您感兴趣的事件(例如 仅推送事件)。
如果由于网络限制无法使用 Webhooks,您可以选择让 Jenkins 定期轮询 GitHub 查找更改。通过在作业配置中选择 Poll SCM 选项来实现。
Jenkins 对检测到的更改所采取的操作在 Jenkinsfile 中定义,该文件包含了 Jenkins 管道的所有阶段。它被提交到源代码管理中,提供了一种便捷的方式来管理版本,并允许在多个作业间共享。
一个基本的 Jenkinsfile,用于 CI/CD 工作流 —— 拉取更改、运行单元测试、检查是否通过,然后如果通过则部署到下一个环境 —— 可能类似于这样:
#!groovy
node
{
def SF_CONSUMER_KEY = env.CONNECTED_APP_CONSUMER_KEY_DH
def SERVER_KEY_CREDENTALS_ID = env.JWT_CRED_ID_DH
def TEST_LEVEL = 'RunAllTestsInOrg'
def SF_INSTANCE_URL = env.SFDC_HOST_DH
def SF_USERNAME = env.HUB_ORG_DH
def sfdxcli = tool 'sf'
在这一部分,我们设置了一些变量。由于我们要引用凭证,建议不要将它们硬编码到 Jenkinsfile 中,而是从运行 Jenkins 的服务器上的环境变量中获取它们。设置好这些后,我们可以开始管道的第一阶段,具体如下:
stage('Pull changes')
{
echo 'Pulling changes from the repository'
checkout scm
}
管道的这一阶段仅仅是从我们的源代码管理中拉取最新的更改,以便 Jenkins 使用。在文件的下一部分,我们可以将所有其他内容封装在我们希望用于与 Salesforce 交互的凭证集内,以便代码块中的所有阶段都使用相同的详细信息。这些凭证是以 JSON Web Token (JWT) 文件的形式提供的,并通过引用该文件将其添加到配置中——有关创建此文件以及在 Salesforce 中连接应用的说明,可以在官方文档中找到,网址为 developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_ci_jenkins_config_env.htm:
withCredentials([file(credentialsId: SERVER_KEY_CREDENTALS_ID, variable: 'jwt_key_file')])
在设置好这些凭证后,我们可以对工作环境做类似的操作,这样所有的命令都会在我们刚刚从源代码管理中提取的代码上下文中运行:
{
withEnv(["HOME=${env.WORKSPACE}"])
现在我们已经设置好了构建环境,我们可以开始将代码移动到我们的 Salesforce 环境。在这第一步中,如下所示,我们使用我们的凭证来进行 SFDX Dev Hub 的身份验证:
{
stage('Auth to Salesforce')
{
echo 'Authenticating to Salesforce'
rc = bat returnStatus: true, script: "\"${toolbelt}\\sfdx\" force auth jwt grant -i ${SF_CONSUMER_KEY} --username ${SF_USERNAME} -f \"${jwt_key_file}\" -d -r ${SF_INSTANCE_URL} -a HubOrg"
if (rc != 0) { error 'hub org authorization failed' }
println rc
}
一旦我们的 Dev Hub 认证通过,我们就可以为我们的代码测试创建一个新的临时组织,如下所示:
stage('Create scratch org')
{
echo 'Creating scratch org'
script
{
rc = bat returnStatus: true, script: "\"${toolbelt}\\sf\" org create scratch --target-dev-hub HubOrg --set-default --definition-file config/project-scratch-def.json --alias ciorg --wait=10"
if (rc != 0)
{
error 'Salesforce test scratch org creation failed.'
}
println rc
}
}
现在我们可以在下一个阶段将更改推送到新创建的临时组织,具体如下:
stage('Push To Test Scratch Org')
{
echo 'Pushing changes to test scratch org'
script
{
rc = bat returnStatus: true, script: "\"${toolbelt}\\sf\" project deploy start --target-org ciorg"
if (rc != 0)
{
error 'Salesforce push to test scratch org failed.'
}
println rc
}
}
此时,我们已经有了一个新创建的临时组织,里面包含了我们最新的更改。我们可以使用它来运行完整的单元测试套件,并确保我们的测试通过,在我们的 CI/CD 管道的另一个阶段中,如下所示:
stage('Run tests in scratch org')
{
echo 'Running tests in scratch org at test level ${TEST_LEVEL}'
script
{
rc = bat returnStatus: true, script: "\"${sfdxcli}\\sf\" apex run test -o ciorg -l ${TEST_LEVEL} -r tap -d test-results"
if (rc != 0)
{
error 'Salesforce test run failed.'
}
println rc
}
}
最后,我们通过删除临时组织来整理工作——这有助于保持我们 Salesforce 开发中心中活动临时组织的数量在上限之内:
stage('Delete scratch org')
{
echo 'Deleting scratch org'
script
{
rc = bat returnStatus: true, script: "\"${toolbelt}\\sf\" org delete scratch --target-org ciorg --no-prompt"
if (rc != 0)
{
error 'Salesforce test scratch org deletion failed.'
}
println rc
}
}
}
}
}
这个 Jenkinsfile 使用的是声明式管道语法,它比脚本化管道语法结构更加严格。它以 node 关键字开始,表示管道的开始。
每个阶段包含一个或多个要执行的步骤。正如你所看到的,这种结构与我们在上一节中介绍的 GitHub Actions 相似。
checkout scm 命令是一个内置的 Jenkins 命令,用于从 Jenkins 作业中定义的仓库中获取源代码。
其他各种步骤都运行 Salesforce CLI 中的命令。这是一个非常基础的例子;一个真实的 Jenkinsfile 会更为复杂。例如,您可能想要添加错误处理、根据作业结果发送通知,或者为代码分析或集成测试等任务添加阶段。值得注意的是,Jenkins 功能强大,但设置比 GitHub Actions 更为复杂,因此值得花时间熟悉这个工具,并更详细地了解 Jenkinsfile 的工作原理。官方 Jenkins 网站 jenkins.io 提供了大量的资料,其中包括《Jenkins 手册》 – www.jenkins.io/doc/book/。
Salesforce 特定工具
在 Salesforce 开发的世界里,迫切需要一些专门为适应 Salesforce 独特架构和开发范式而设计的工具。其中两款具有特别重要性的工具是 SFDX 和 Salesforce CLI,它们在 Salesforce 开发过程中扮演着核心角色,并提高了 CI/CD 流水线的效率。
SFDX 是 Salesforce 开发的一种方法,得到了 Salesforce 提供的一套开发工具的支持,它不仅促进了源驱动开发,还促进了团队协作,并持续协调测试和部署。它采用了以生态系统为中心的方法,确保与 DevOps 领域内其他工具的无缝集成。Salesforce CLI 是 SFDX 的一个基本组件,作为命令行工具,它允许跨 Salesforce 组织脚本化执行多种任务,从创建临时组织和管理数据到执行 Apex 代码。
SFDX 和 Salesforce CLI 的真正潜力在于与外部 CI/CD 工具(如 Jenkins 和 GitHub Actions)集成时展现出来。尽管这些工具功能强大,但它们缺乏对 Salesforce 元数据驱动和多租户架构的内在理解。这正是 SFDX 和 CLI 的优势所在,它们在这些外部工具与 Salesforce 特定任务之间架起了桥梁。
想象一下这样一种场景:一个开发者将代码推送到 GitHub 仓库。GitHub Actions 可以启动一个工作流,利用 Salesforce CLI 创建一个新的临时组织,推送更新后的代码并执行 Apex 测试。类似地,Jenkins 可以在其构建步骤中加入 Salesforce CLI 命令,使其能够处理诸如创建和管理临时组织或部署元数据等任务。
除了触发动作和促进工作流外,SFDX 和 Salesforce CLI 还在 Salesforce 开发中强制执行最佳实践。SFDX 的源驱动方法鼓励开发人员将版本控制系统作为真相的来源。Salesforce CLI 拥有广泛的命令范围,促进了自动化,从而减少了错误并提高了 Salesforce 代码库的质量。
SFDX 和 Salesforce CLI 由 Salesforce 持续更新。它们与 Salesforce 自身的开发保持紧密集成,始终与最新的 Salesforce 功能和改进保持一致。因此,将这些工具纳入 CI/CD 流水线,不仅满足了当下的需求,还为未来 Salesforce 开发的进步做好了准备。
SFDX 和 Salesforce CLI 是构建高效、有效的 Salesforce CI/CD 流水线的重要工具。它们提供了 Salesforce 平台与外部 CI/CD 工具(如 Jenkins 和 GitHub Actions)之间的关键连接,能够处理 Salesforce 特定的任务。通过充分利用这些工具,你可以构建一个强大、自动化并具有未来适应性的 CI/CD 流水线,彻底革新你的 Salesforce 开发流程,减少手动操作,最小化错误,加速交付。
CI/CD 流水线的实际应用
一旦为 Salesforce 开发建立了自动化的 CI/CD 流水线,新的纪律和实践便会涌现,从而充分利用其能力。最直接的好处是流水线仪表板提供的实时可视化,能够清晰展示整个流程的健康状况。构建状态、测试结果、部署记录以及其他关键指标都可以进行监控,从而快速识别流水线故障,并在问题成为重大问题之前迅速进行故障排除。
增强的可视化有助于将质量门控等实践纳入流程中。例如,可以强制执行代码覆盖率等必需的标准,确保发布前的质量。通过 CI,开发人员有信心频繁地将代码合并到共享的主干仓库中,从而促进有效的基于主干的开发。
另一个主要优势是流水线如何缩短并加紧反馈周期。自动化测试和快速构建/部署周期意味着开发人员可以在任何更改后几乎即时收到反馈。问题可以立即被发现并解决,避免了更多工作的堆积。
自动化还降低了频繁发布时的风险。高级团队可以实现自动回滚程序,直接从流水线中即时逆转不良部署。当然,流水线指标的数据可以进行分析,寻找调整的机会——如交付时间、部署频率和变更失败率等关键指标能够揭示持续改进的领域。
借助流水线所提供的新可视化和自动化,开发人员不再需要进行繁琐的手动质量检查,而可以将精力集中在编写高质量的代码上。他们可以更加自信地加速发布,因为自动化在背后处理测试、质量执行和流水线推进。这使得团队能够充分利用现代开发实践,从而提高敏捷性。
总结
在本章中,我们探讨了使用免费工具实现 Salesforce CI/CD 流水线的几种解决方案。在查看 GitHub Actions 和 Jenkins 的设置时,我们发现流水线的基本步骤是相同的,但在具体实施上有所不同。
我们还看到,这些工具在很大程度上依赖于 Salesforce CLI 工具和 SFDX 方法来管理元数据,以执行构成 CI/CD 流水线的步骤。当然,使用 SFDX 并非强制要求——任何能够利用 Metadata API 的工具都可以替代,但值得注意的是,构建用于管理整个流程的必要脚本是一个相当大的开发和维护工作量,需要由负责管理 DevOps 工具链的人来完成。通过采用专为 Salesforce 设计的 DevOps 解决方案和平台,可以减轻这一负担。我们将在后续章节中介绍市场上的一些选项。
在下一章中,我们将继续完善我们的整体 DevOps 实施,通过了解工单系统来实现,这些系统可以更好地管理工作项,不仅有助于清晰地呈现开发变更的进展,还能将这些变更拆分成更小的工作单元,从而有助于 DevOps 原则中的早期发布和频繁发布。
第八章:工单系统
在本章中,我们将讨论在工单系统中跟踪 Salesforce 变更的好处,以及它如何有助于更高效的 DevOps 流程。然后,我们将介绍三款最常用的工具来跟踪 Salesforce 中变更的进度:
-
JIRA 是由 Atlassian 开发的一个问题跟踪和项目管理软件,允许团队规划、跟踪和发布软件。
-
Asana 是一款工作管理平台,帮助团队在项目中协作、沟通和协调工作。
-
Azure Work Items 是在 Azure DevOps 中跟踪的开发任务,用于管理敏捷开发过程并更频繁地发布软件。
到本章结束时,您不仅会清楚地了解这些不同类型的工具包之间的区别,还会知道何时使用它们,以及如何在 Salesforce 中构建它们。
技术要求
本章并非旨在提供涉及的产品的逐步指南,但如果您希望深入了解它们,每个产品都提供了一个免费的试用版本以供学习:
-
Asana –
asana.com/ -
Azure DevOps –
azure.microsoft.com/en-gb/free
跟踪工作带来的好处
任何成功项目的基础都依赖于组织良好的任务管理和跟踪方法。在 Salesforce DevOps 中使用工单系统提供了多重优势。
透明度
所有任务及其状态对团队成员可见,促进开放的沟通并推动团队合作。当每个人都能看到需要做什么以及由谁来做时,就能消除重复的工作,并使协调变得更容易。
这种可见性在多个层面上提供了好处——对个别团队成员、团队经理、跨职能利益相关者和领导层都有帮助。对于团队成员来说,所有任务和当前状态都集中在一个工单系统中,让每个人都能看到需要完成的工作以及由谁负责。开发人员可以立即查看哪些工单是进行中,哪些是代码审核中或待测试。测试人员可以查看哪些项目排队等待验证。
实时的可见性消除了重复劳动,因为团队成员可以基于最新的信息进行协调。团队成员不会浪费时间在相同的任务上,或者错过那些阻碍进展的瓶颈。对于管理者来说,工单的透明度有助于评估团队工作负载、识别瓶颈和评估资源需求。工单积压提供了规划容量的数据。等待接受的工单揭示了哪些流程在放慢速度。
在产品、用户体验、开发和质量保证等团队之间,工单系统提供了跨职能的透明度。利益相关者可以监控需要合作的功能或项目的进展。了解彼此的工作流能够促进更好的协调。
对于领导层来说,工单数据会汇总成报告,反映完成率、周期时间和吞吐量。这种高层次的透明度帮助高管了解团队生产力、优先级排序以及战略目标的进展情况。
责任
每个工单都分配给特定的团队成员,这有助于跟踪个人绩效。通过将工单与个人绑定,明确了谁负责完成具体任务,支持生产力监控。
将工单分配给特定人员后,谁负责这项工作就不再存在任何模糊之处。责任明确,避免了因为没有人负责而导致任务被忽视。团队成员可以因按时完成任务和交付结果而被追责。
将工单与负责人绑定,有助于在个人层面监控生产力。团队成员和经理可以快速检查某人分配的工单状态,以评估工作负载和完成率。这有助于跟踪绩效和进展。
如果某些工单被阻塞,显然可以知道需要联系哪位团队成员来清除障碍。同样,当工单超出服务水平协议(SLAs)时,可以通知责任人采取紧急行动。从项目管理的角度来看,能够按负责人过滤和查看工单,使得衡量团队容量和分配工作负载变得容易。为工单添加或移除团队成员有助于适当扩展资源。
除了分配任务之外,一些工单系统还允许设置截止日期、时间估算和提醒。这些功能提供了进一步的责任保障,帮助团队成员管理自己的时间和优先事项。
优先级排序
工单系统还促进了优先级排序。工单可以标记优先级或添加标签,从而使团队能够首先关注最为关键的业务事项。
一种方法是为工单分配优先级,例如 P1、P2 和 P3。P1 工单是需要优先处理的关键问题或高优先级特性。P2 和 P3 工单优先级较低,可以排在更高优先级的工作后面。
团队还可以根据工作类型(如 Bug、改进、新特性等)对工单进行分类。影响生产系统的关键 Bug 会被优先处理,而特性增强则会排在后面。
在敏捷框架(如 Scrum)中,优先级排序通过产品待办事项来管理。待办事项按价值排序,最高价值的事项排在最前面,优先在接下来的冲刺中完成。一些工单系统内建了验证和排名功能,在将工单添加到待办事项之前,根据业务价值对请求的工作进行排序。这为待办事项提供了优先级的“入口关”。在冲刺待办事项中,还可以根据估算工作量为工单分配点数,从而按照优先级排序。点数较大的工单会更早开始处理。
在团队层面,每日站会提供了重新调整优先级的机会,以应对紧急或被阻塞的任务。调整工单优先级能够让团队保持专注。从项目组合的角度看,通过战略主题或目标对工单进行标记,帮助领导层评估多个项目和产品之间的优先级。
文档记录
此外,工单系统提供了集中化文档记录。避免了有价值的信息分散在各种工具和对话中,任务的详细信息会在每个工单内进行记录,形成一个随着时间推移而持续的知识库。这包括背景信息、需求、验收标准、设计规格、配置、流程、代码片段、测试步骤、沟通记录等。
没有使用工单系统时,这些重要的工作细节会分散在 Slack 对话、电子邮件、维基、文档、便签和个人笔记本中。关键信息被孤立,难以找到。然而,使用统一的工单系统时,与任务相关的所有内容都会以有序的方式记录在一个地方。团队成员可以通过查看工单的历史和附件,轻松了解工单的进展。
搜索工单可以快速找到过去的解决方案,并将其应用于当前的问题或需求。它防止了重复工作,避免了在类似工作已完成并记录的情况下再次进行相同的努力。记录良好的工单为组织创建了记忆,即使团队成员离开或角色发生变化,这些信息也能持续存在。历史工单成为了有价值的参考资料和培训资源。
从流程的角度来看,工单系统能够规范化团队之间的文档实践。可以定义模板工单类型,以指导一致的信息收集,确保任务在工作流中流转时信息一致。
协作
在之前的章节中,协作是成功的 Salesforce DevOps 策略中一个反复出现的要素。拥有一个统一的工单系统也有助于跨团队的协作,例如产品、开发、质量保证、支持等。它为跨职能团队提供了一个共享的真实信息来源,确保透明度。
这种透明性具有很大的实际优势。虽然个别事项仍会在初期阶段由产品负责人控制,但可视化的待办事项清单为开发团队提供了一个机会,让他们能够参与到故事的讨论中,特别是当他们觉得某些故事可能过大或过于复杂,需拆解时。它还允许团队为故事绘制出高层次的实施计划,并将它们整理在一起,这样就不会让个别开发人员独自创建解决方案,也能确保无论谁负责工单,都有一定的一致性。
票务系统为这些不同的团队提供了一个共同的平台,使他们可以了解彼此的工作流。例如,产品团队可以监控工程工单,以跟踪新功能的进展。支持团队可以检查待解决的 bug 修复状态。跨部门的洞察力有助于及早识别依赖关系和风险。提前看到障碍使得团队可以主动合作解决问题,而不是后期做出反应。
工单提供了一个集中的沟通渠道,不仅仅是状态更新。团队可以使用@mention功能提及相关成员进行意见反馈、澄清需求、请求批准或通过评论进行问题升级。对于复杂项目,不同团队的人可以共同被指派到协作工单上。这确保了通过共同拥有实现一致性。
一些票务系统具有敏捷项目管理功能,例如看板。它提供了一个可视化的协作工作空间,用于管理在不同阶段流转的工单。将问题转换为可操作的工单,反之亦然,有助于简化团队之间的交接。无缝的过渡可以减少跨职能工作流程中的遗漏。看板的另一个好处是能够限制在生命周期中的任何时刻进行中的工作量。这不仅帮助防止开发团队过载,还能提供清晰的流程效率可视化。某一列中的限制可能意味着任务流转不够迅速,或者任务进入过快,或两者兼有。
报告与分析
票务系统收集的有价值数据可以用于生成有见地的报告和开发工作流指标。这支持基于数据的决策和流程改进。常见的工单报告包括按分配人、工单类型、优先级、项目等总结工作量。这些视图有助于识别瓶颈和资源缺口。
趋势报告跟踪诸如工单开闭情况等内容。关于周期时间的分析——从工单创建到完成——有助于监控开发过程的效率。按工单类型或项目的周期时间为分析提供了需要简化的领域的洞察。仪表板视图可以直观地跟踪工单积压和服务水平协议(SLA)遵守情况。其他关键指标包括交付时间、吞吐量和在制品限制——所有这些都有助于优化流程。
根据工单记录的时间进行报告有助于基于历史速度提高发布和迭代计划的准确性。通过比较预估时间和实际时间,可以改进工作量估算。对于生产力,报告可以显示各个团队成员的工单完成率。分析模式可能表明需要进行培训、工具改进或资源重新分配。
总体而言,数据分析有助于关联流程变化如何影响工单吞吐量和周期时间。这指导优化工作重点,以实现最大收益。
潜在的陷阱
虽然 Salesforce DevOps 中的工单系统提供了相当大的优势,但必须承认它们可能带来的潜在问题。一个主要的风险是将积压的工单误认为是实际的计划。一个良好的维护的积压工单无疑是有益的,但它不能替代全面的计划,比如季度路线图,这些计划能提供项目目标和时间线的更广泛战略视角。
另一个挑战在于工单中内容的性质。单纯依赖工单进行文档记录可能导致信息的零散和分散。这种碎片化使得形成项目的连贯、最新的全貌变得困难,而如果有良好组织和集中管理的文档可用,则可以避免这种情况。补充强有力的文档管理实践是确保清晰和连续性的关键,不能仅依赖工单系统。
最后,如果不加以谨慎管理,团队之间的工单交接可能导致操作孤岛。这与 DevOps 的理念相悖,DevOps 强调不同团队之间的协作与整合。必须培养一种文化,使工单系统增强沟通与合作,而不是在组织的不同部分之间设立壁垒。
JIRA
JIRA 由 Atlassian 开发,是最受欢迎的工单和项目管理工具之一,广泛用于错误跟踪、问题跟踪和敏捷项目管理。它的主要优势之一是灵活性。团队可以定制他们的工作流程、创建自定义字段,并使用各种插件来满足他们的独特需求。它与 Salesforce 无缝集成,提供统一而高效的工作空间。
在 Salesforce DevOps 环境中,JIRA 可以通过为每个任务、错误或功能创建工单来简化工作流程。这些工单可以被分配、优先级排序,并跟踪直到完成。JIRA 的报告功能为团队表现提供了有用的洞察,而其强大的搜索功能则帮助快速查找问题或工单。
JIRA 在管理端到端 Salesforce 开发过程和通过其灵活的工作流程和可定制性增强 DevOps 协作中起着至关重要的作用。
让我们来看一个典型的使用 JIRA 来管理任务的项目工作流程。我们的示例假设了一个由多个角色组成的相对较大的企业团队,因为这是 JIRA 实施中最典型的使用场景。
JIRA 项目生命周期
在开始季度路线图规划过程时,产品经理依赖 JIRA 史诗来定义即将发布的主要主题、功能和计划的举措。这些高层次的史诗为团队确立目标和方向。当产品团队进一步深入细节时,这些广泛的史诗会被细化为更具体的用户故事、错误、任务和子任务。这个问题的层级结构既捕捉了大局视角,也涵盖了实现这些目标所需的增量工作。
到达冲刺规划阶段时,JIRA 包含一大批准备执行的明确定义的问题。Scrum 团队充分利用 JIRA 的敏捷能力来估算问题,应用故事点,并为冲刺协商范围。通过映射依赖关系和将问题结构化为连贯冲刺,释放计划开始形成。分配所有者,讨论风险,并挑战假设,以确保团队一致。
一旦冲刺开始,开发人员将负责 JIRA 问题,为复杂问题构建解决方案。JIRA 与整个开发工作流程紧密集成,以实现可追溯性和自动化。用户故事在 Git 的功能分支中进行工作,引用 JIRA 问题编号。所有提交都解释了所做的工作,并在提交消息中映射到问题。用于同行代码审查的拉取请求也指出它们解决的问题。
Git 与 JIRA 之间的这种连接提供了与问题相关的代码更改的端到端可追溯性。它还提供了自动化机会。代码构建可以接受 JIRA 问题 ID,自动将失败和测试结果链接为注释或子问题。通过工作流程阶段转换问题可以触发持续集成中的事件,如构建作业,部署或通知。
例如,当开发人员完成用户故事的编码后,他们将功能分支合并到主分支。这会触发一个持续集成作业,运行 Apex 测试和静态分析。如果出现任何失败,它们将作为 JIRA 中故事的子问题记录,供开发人员解决。成功的构建可以自动将代码更改部署到 Salesforce 沙箱进行 QA 测试。然后,JIRA 问题将进入 QA 测试和验证工作流程的阶段。
QA 工程师通过自动化验证在 Salesforce DevOps 中扮演着积极角色,从而加速发布周期同时提高质量。JIRA 通过链接的测试用例,缺陷和与 CI/CD 管道的紧密集成来支持这一点。QA 记录详细的测试步骤,结果,问题,媒体和其他问题评论,以验证用户故事是否符合验收标准。
为了高效的回归测试,他们使用诸如 Selenium 和 Jasmine 的框架来构建自动化测试套件进行 UI 测试,以及使用 Apex 单元测试进行逻辑测试。这些自动化测试作为持续集成的一部分执行,针对功能分支和主线代码。QA 设置质量门,只有在测试通过并且代码覆盖率达到阈值时,构建才能继续进行。
静态代码分析也包含在构建中,以检查漏洞并强制执行围绕代码质量和最佳实践的自定义规则集。来自任何这些检查的失败都作为子问题或错误记录,提供了质量演变的审计追踪。
当所有自动化验证通过并且质量保证完成探索性测试时,用户故事会通过 JIRA 工作流转移。这往往会触发持续交付工作流程,自动在 Salesforce 沙盒中部署和验证更改。通知下游团队进行用户验收测试。然而,在此方法中有一些需要注意的地方——如果由于某些原因部署失败,您还需要处理并将状态回滚到之前的状态,这显然会更加复杂。值得注意的是,一些团队在他们的 JIRA 看板上实施了“泳道限制”,以防止太多工作停留在任何一个状态。因此,即使您设法将与失败部署相关联的工单状态回滚,可能也没有足够的空间将其移回工作进行中的状态。为了解决这些问题,许多团队采取了相反的方法,即仅在成功部署后更新 JIRA 工单状态。
这种对单元测试、集成测试、UI 测试、性能测试、安全性测试、合规性测试和部署测试的全面自动化,可以快速反馈质量问题。JIRA 提供了关于测试、验证和与交付问题相关的代码更改的可追溯性,同时自动化释放了质量保证人员,让他们可以进行更高价值的测试,同时强化质量标准。
JIRA 在促进 Salesforce DevOps 协作中所需的沟通节奏和透明度方面不可或缺。围绕 JIRA 问题展开的站立会议能够快速检查阻碍因素和进展状态。回顾会议利用 JIRA 数据中的周期时间和速度,持续改进流程。
即使没有明确的敏捷框架,JIRA 也有助于嵌入 DevOps 实践。将工作拆分为小问题可以实现快速交付和反馈。通过定义的工作流跟踪问题,实现管道编排。基于 JIRA 转换的自动交接增加了跨团队的协作。
强大的报告和仪表板突出显示趋势、风险和依赖关系。活动流和通知保持每个人对实时问题变更的了解。JIRA 提供的这种透明度有助于跨部门共享责任。
在 JIRA 中记录的需求和验收标准促进了开发人员、质量保证、安全性以及其他团队之间的协作。通过早期对齐问题详情而非最后一刻的惊喜,实现了流畅的交接。
JIRA 提供了数字化支撑,使 Salesforce 团队能够根据实时数据快速审视和调整。与版本控制、测试自动化和 CI/CD 流水线的紧密集成加速了反馈周期。
JIRA 围绕着站立会议、回顾会议、冲刺规划和工作协调展开。它是一款不可或缺的工具,赋予团队更快交付的能力,同时提升质量和流程。JIRA 可以帮助巩固持续改进、透明化、自动化和协作的环境,这些是 DevOps 的基础。
一个高层次的 JIRA 工作流
你的第一步应该是为 Salesforce 发布创建一个 JIRA 项目,其中包括用户故事、缺陷、任务等问题类型。在这个项目中,你应该创建史诗来捕获发布的主要特性和任务,然后将这些史诗拆分为用户故事。
开发人员从待办事项中选择用户故事进行冲刺计划。故事在进行冲刺之前会被估算和优先排序,然后将冲刺中的用户故事移至进行中。
开发人员将代码提交到 Git 功能分支,引用与用户故事相关的 JIRA 问题编号。当一个用户故事的工作完成后,开发人员在功能分支准备好进行审查时,会打开拉取请求。拉取请求会链接回 JIRA。
在经过同事的一些代码审查后,拉取请求会被合并到主分支,这可能会触发自动构建。这些构建会执行 Apex 测试和静态代码分析,任何失败都会作为问题追踪到 JIRA 中。
成功的构建可以将代码部署到完整的沙盒环境中进行 QA 测试。QA 测试用户故事,并将任何错误记录为 JIRA 中的问题,供开发人员修复。当用户故事的接受标准满足时,QA 会将该故事移动到QA 已批准状态。
项目经理应审查已完成的故事,由产品负责人提供最终批准。项目经理随后将批准的故事批量部署到生产环境,使用变更集进行部署。
发布经理通常协调用户验收测试(UAT)过程和最终的生产部署。在成功发布后,用户故事将标记为关闭。
在发布后的最终评审阶段,可以收集团队速度、缺陷率等指标,之后该过程会在随后的冲刺和发布中重复进行。
这涵盖了主要步骤,如冲刺计划、CI/CD、与问题相关的代码更改、QA 测试、审批和发布。这个工作流程可以在 JIRA 中根据每个团队的需求高度定制——这只是一个相对典型的示例。
Asana
Asana 提供了一个强大的工作管理平台,旨在帮助团队有效协调、跟踪并交付组织内的工作。Asana 的核心功能是支持创建灵活的工作流,这些工作流映射到团队流程,并具有可定制的阶段来跟踪任务状态。任务可以根据每个团队的需求,通过列表视图、看板样式的板视图或日历视图进行组织。
选择 Asana 作为首选项目管理平台,可以显著提升 Salesforce 开发团队在从新功能请求到生产环境缺陷修复等方面的计划、跟踪和协作能力。通过在多个不同的 Asana 项目中映射整个开发生命周期,团队可以在整个过程中获得端到端的可视性和控制。
例如,创建单独的项目来管理待办事项、开发中、代码审查、QA 测试和生产发布,提供了一种逻辑的方法,将工作从创意到部署的各个阶段进行分段。团队还可以通过根据工作流、应用程序或项目进一步划分每个项目的部分来进行组织。这有助于将相关任务聚集在一起,并确保工作的一致性。
在此基础上,我们来看看 Asana 如何从最初的需求收集到最终发布,优化生产力和协调工作。
Asana 项目生命周期
首先,通过为每个新特性或增强功能请求创建任务,简化了需求收集过程。任务可以包括高级描述、预期交付时间、分配给相应的开发人员或团队、相关文档或工单的链接,以及任何其他支持细节。
在 Asana 中捕捉请求提供了可追溯性,并且便于后续流程中的参考。可以定义自定义字段以匹配团队的工作方式——例如,标明每个任务的优先级、工作量、依赖关系或相关发布版本。
在冲刺规划和待办事项梳理过程中,管理人员可以检查未完成请求的概况,并将最具价值的任务安排到即将到来的迭代中。设置任务之间的里程碑和依赖关系,确保功能的正确顺序和交付。
一旦任务准备好进行开发,就可以将其移入开发中项目。这为开发人员提供了清晰的工作负载视图。随着工作的完成,开发人员可以轻松更新任务状态、记录工时、附加截图或代码片段,并在 Asana 内提供任何其他相关评论。
对于开发人员来说,Asana 作为一个中央工作空间,用于跟踪和执行他们在开发阶段分配的任务。一旦在冲刺规划期间识别出工作任务,相应的任务会在开发中 Asana 项目中创建,并根据开发人员的角色和能力分配给他们。
这些任务包含所有必要的上下文信息,如描述、截止日期、故事点、链接到工单或规范的链接,以及标明正在处理的应用程序或特性的标签。通过将所有这些信息集中在 Asana 中,开发人员可以清楚地知道需要做什么,而无需翻阅收件箱或聊天记录。
随着工作的开始,开发人员可以将较大的任务分解为更细粒度的子任务,以代表完成的各个阶段。他们还可以直接在 Asana 中记录工时,以便捕捉每个任务所花费的时间。内联评论允许开发人员提供进度更新、提出澄清问题或请求反馈。
代码示例、截图和其他相关资料可以在生成时附加到任务中。提及同事会将他们引入到对话中。这创建了一个持续的进展记录和知识共享,伴随任务一起存续。
对于被阻塞或延迟的任务,开发人员可以通过更新状态并通知管理者迅速提出警告。完成后,任务会标记为准备好进行 QA,并自动将其路由到工作流程的下一个阶段。与 Git 和 Jenkins 等源代码管理工具的集成意味着代码提交和构建可以自动推动任务通过流水线。
功能完成后,工作转入代码审查项目,由 QA 工程师根据规范验证实现。如果发现问题,可以生成与父任务关联的新 bug 任务,便于追踪。这加快了开发者的反馈循环。一旦 QA 批准,经过充分测试的代码将进入用户验收测试和预发布阶段。
可以配置自动化集成,以在每个环境成功部署后更新任务状态。这为团队节省了手动跟踪发布活动的时间。随着工作接近生产准备,Asana 中的变更日志为管理者提供了关于即将发布的完整背景。他们可以立即审查所有已完成的任务、受影响的组件、依赖关系和预期的影响。
这种透明度使得管理者始终保持信息更新,并能及早发现任何障碍。团队成员还可以在评论中被@提及,将他们拉入讨论或征求对正在进行工作的反馈。如果有额外的需求,可以在保留与原始父任务关联的情况下,定义新的子任务。
在完整的叙事可见的情况下,任何临时的变更都可以最小化。签字后,点击批准的生产任务上的Go按钮。部署后的同行评审和抽查提供了验证,确保一切顺利发布。
任务完成后,在 Asana 中标记为已关闭,从开始到完成创建一个永久的审计轨迹。正确估算任务时,每个冲刺中关闭的任务可以反映团队的工作速度,这有助于未来的规划和资源配置。检查每个任务的周期时间还可以揭示环境之间的任何延迟。
需要持续管理 Asana,以制定基于角色的权限、定制字段、设置自动化和监控采用情况。项目和任务模板有助于规范最佳实践并为团队提供起步的基础。定期的 Asana 培训将确保团队成员能够充分利用其全部功能。
与其他基于票证的任务管理系统类似,Asana 对成熟的 DevOps 团队中的沟通和协作作出了重要贡献。在站立会议中,分配给每个开发人员的任务一目了然,最新的更新可见。团队成员可以轻松查看被阻塞的任务、新的障碍以及解除阻碍所需的帮助。管理者能获得各工作线程的速度情况。
回顾环节通过查看历史 Asana 数据(如周期时间、工作负载分配和开发人员的完成率)得到增强。这激发了基于数据的根本原因分析和流程改进。
通过将所有候选故事和缺陷按优先级、范围和工作量详细信息在 Asana 中进行排序,支持对待办事项的整理。这些信息为决定即将进入的冲刺提供指导。
共同的联系点是 Asana 将所有任务、状态和支持性上下文集中化,便于沟通。与聊天或电子邮件不同,这些知识会附加在任务上,供未来参考。Asana 的灵活性支持任何团队仪式的偏好节奏。
通过提供透明的信息,明确谁在做什么以及何时完成,Asana 推动了协作式问题解决、消除障碍和持续改进——这些是 DevOps 的核心原则。通过这种方式,Asana 对于 Salesforce 团队在 DevOps 之旅中的对齐、可见性和速度做出了重要贡献。
高级 Asana 工作流
首先创建 Asana 项目,表示 Salesforce 开发生命周期的每个阶段(例如,待办事项、开发中、代码审查、QA 测试和生产发布)。在每个 Asana 项目中,为不同的工作流创建部分,如新特性、缺陷、增强功能等。当在 Asana 中创建新任务时,将它们与项目的对应 Git 仓库和包含每个任务代码更改的分支关联起来。
当开发人员在任务上工作时,他们会频繁地将代码更改提交到与相关 Asana 任务 ID 相对应的 Git 分支。完成开发后,开发人员将其特性分支推送到 Git 并将 Asana 任务移至代码审查。
然后,QA 团队拉取特性分支,在本地验证 Asana 任务中描述的更改,并将任何失败记录为新任务。一旦通过审核,QA 团队会将已验证的代码合并到 Git 中的发布候选分支。这将触发下游环境的部署。
在最终生产部署之前,会对 Git diff 和 Asana 变更日志进行审查,作为最后的检查。发布分支部署到生产环境后,会将其合并到主分支。
所有与发布相关的任务都在 Asana 中关闭,并且可选地将 Git 提交日志链接到 Asana 任务,以保持端到端的可追溯性。作为发布审查过程的一部分,会从 Git 中获取代码覆盖率和质量指标,以提供关于开发人员表现和需要改进的领域的反馈。
通过将 Git 版本控制集成到这一工作流中,代码更改与 Asana 中的项目计划和测试过程同步。这提供了全面的可见性和可追溯性。
Azure 工作项
与前两种解决方案不同,Azure 工作项是一个更大整体 DevOps 解决方案的子集——该解决方案面向多个平台,而不仅仅是 Salesforce。Azure DevOps 提供了一套完整的协作开发工具,包括 Azure Boards 及其包含的 Azure 工作项,用于工作追踪。当我们专门看与 JIRA 或 Asana 的对比时,Azure Boards 及其工作项功能帮助团队规划、跟踪并讨论整个开发周期中的工作。
Azure DevOps 中的工作项是一种跟踪任务、缺陷、功能等的方式。它们可以组织成一个层次结构,因此你可以将一个大型功能拆解为可管理的任务,并在每个层级上跟踪进展。你可以通过看板、待办事项、定制仪表盘和报告工具来可视化你的工作。
Azure DevOps 充当开发任务的真实来源,而 Salesforce 则直接从服务、销售和市场团队提供客户洞察。查看每个数据源,并且从不同的角度了解 Salesforce 系统当前的状态,能够创建一个有价值的优先级视图。例如,客户服务代理可以在 Salesforce 案件中查看 Azure DevOps 中的 bug 和功能,实时更新客户问题的解决情况。代理可以轻松地将 bug 与支持案件关联起来,向开发人员展示客户的影响。
同时,开发人员可以看到哪些 bug 与高价值账户和即将成交的机会相关。这帮助技术团队将最关键的缺陷优先处理,而不是那些次要的项。通过看到每个工作项的完整上下文,能够实现更智能的缺陷处理,并有效利用开发资源。更快解决高优先级缺陷有助于提高客户留存率和满意度。
另一方面,当开发团队完成与 Salesforce 记录相关的工作项时,变更会立即进行双向同步。例如,当开发人员解决一个关键 bug 时,客户服务代理会立即在 Salesforce 中看到更新。这避免了不必要的来回沟通,并通过集中数据保持客户的更新。
通过这种双向同步,任一系统中的工作项更新始终保持实时同步。避免过时或重复的数据确保了准确性,并在各部门之间提供了唯一的真实来源。这提高了在缺陷解决方面的协作效率。
进一步增强协作,Salesforce 用户可以在熟悉的 CRM 视图中轻松跟踪 Azure DevOps 工作的进展。例如,客户服务经理可以创建自定义的 Salesforce 仪表盘来监控 bug 解决的时间表。客户经理可以直接在账户记录中查看为客户规划的功能。所有数据都原生存在 Salesforce 中,因此无需交叉引用不同的系统。这简化了非技术用户与关键开发任务的互动,而无需学习 Azure DevOps。
转到开发人员端,将 Azure DevOps 工作项导入 Salesforce,可以为技术任务提供更深层次的客户洞察。在传统的孤岛模型中,开发人员对客户需求和业务目标的可见性有限。通过将工作项与账户、机会和支持案例关联,每个工作项的完整背景变得清晰。
通过这种以客户为中心的方式,开发人员可以理解某些 bug 背后的体验和挫败感。看到带有精确用户操作步骤的支持案例来重现错误,比传统的孤立票证更能迅速带来清晰度。工程师们获得了对客户旅程的共鸣和感激,从而激发了构建真正解决痛点的功能。
Azure 工作项生命周期
现在,我们深入探讨 Azure DevOps 在 DevOps 生命周期中开发阶段的作用,Azure 无缝集成促进了开发人员的生产力和协作。在一个 Azure DevOps 工作区内,开发团队可以规划敏捷 sprint,创建工作项,管理源代码库,执行构建,管理测试,跟踪缺陷,部署到预发布环境等。
例如,开发人员在处理用户故事时,可以轻松查看所有关联的 bug、测试用例、分支和构建,所有信息都集中在一个地方。这消除了在不同的系统之间切换以拼凑上下文的麻烦。Azure Boards 将连接的项目聚合在一起,提高编码效率,减少开销。在 Boards 内,开发人员可以将具体的任务分配给个人,并跟踪每个任务花费的时间。这个级别的可见性使得能够准确追踪工作负载和 sprint 进展。自动化的燃尽图可以绘制完成进度,帮助识别范围蔓延或需要解决的阻碍。
在任务管理方面,Azure Boards 提供的可定制工作流允许创建子任务、优先级指定、状态更改、分配给个人、跟踪剩余工作等。开发人员可以将较大的故事拆解为可执行的开发项目清单。
在任务管理方面,开发人员使用 Azure Repos 进行安全的源代码管理,支持 Git 和 GitHub。诸如分支和合并等高级版本控制功能使开发人员能够在创建新功能时隔离更改。Repos 在整个编码过程中保护代码完整性。
接下来,通过与 Azure Pipelines 集成,开发人员可以在每次代码变更时自动进行构建、测试和部署,从而提供快速反馈。从提交到部署的完整可追溯性简化了根本原因分析。故障能够迅速被标记,以保持开发速度。
在测试方面,开发人员利用 Azure Test Plans 创建测试用例,并与构建自动集成。测试人员可以轻松跟踪需要执行的测试用例,查看测试运行状态,并记录缺陷。将 bug 与失败的测试用例关联起来加速了解决问题。
在开发过程中,团队利用协作工具,如可自定义的团队仪表盘、内置的维基和讨论线程来提高可见性和协调性。所有内容都集中在 Azure 中,开发人员可以减少任务切换,保持专注。通过将开发生命周期集中到 Azure DevOps 中,开发人员获得了一个敏捷、高效且协作的环境,专为现代开发而设计。将这些功能与来自 Salesforce 的客户数据相结合,形成了开发人员交付创新解决方案所需的完整背景。
高层次的 Azure Work Items 工作流
若要使用 Azure Work Items 跟踪使用 Azure DevOps Repos 作为 Git 提供者的系统中的更改,你首先需要在 Azure DevOps 中设置一个项目。这个项目是你在 Azure Repos 中的代码和在 Azure Boards 中的项目管理活动(包括你的工作项)的集中枢纽。
一旦你的项目建立,下一步就是在这个项目中配置 Azure Repos。这包括初始化一个新的代码库或将现有代码库导入到 Azure Repos。这个代码库将存储你的代码,并跟踪随着时间推移所做的更改。
设置好你的代码库后,重点转向 Azure Boards,在那里你管理你的工作项。这些工作项可以包括特性、用户故事、任务、缺陷等,代表项目的不同方面。关键是将这些工作项直接与 Azure Repos 中的更改关联。这种关联提供了可追溯性,并清晰地记录了哪些代码更改与哪些项目任务相关联。
为了建立这种关联,在提交更改到 Azure Repos 的代码库时,你需要在提交信息中包含对这些工作项的引用。Azure DevOps 会自动将这些提交与提到的工作项链接。例如,在提交信息中加入类似 Fixes AB#123 的短语,将会把该提交与 Azure Boards 中的工作项 123 关联起来。
在 Azure Boards 中,你可以查看每个工作项的开发状态及相关的提交记录。这种可见性让你可以直接从工作项跟踪开发进度,提供了编码和项目管理活动的全面视图。
这个高层次的工作流对于使用 Azure DevOps 进行软件开发的团队至关重要。它确保了代码管理与项目追踪之间的无缝集成,提高了开发过程的整体效率和透明度。
如果需要更详细的说明和最佳实践,你应该参考微软提供的官方 Azure DevOps 文档,其中包含了关于如何设置和管理这些集成的全面指南和逐步教程。
使用 Azure Work Items 工作流与 GitHub
同样可以将 GitHub 用作主要的 Git 提供者,同时仍然能够利用 Azure 工作项的追踪功能。我们首先从 GitHub Marketplace 安装 Microsoft Azure Boards 应用程序,这样就授权了两个系统之间的集成。在 GitHub 中,进入组织设置,我们可以验证 Azure Boards GitHub 应用是否已正确授权。
接下来,在 Azure DevOps 门户中,我们通过GitHub 连接将 Azure Boards 组织连接到指定的 GitHub 账户。在这里,我们指定要与 GitHub 同步的 Azure DevOps 组织、项目和代码库。然后,在 Azure Boards 中的代码库映射部分配置关键映射,将 GitHub 仓库与 Azure DevOps 团队和分支对齐。
配置完集成后,开发人员现在可以在 GitHub 中创建拉取请求并提交代码更改,在提交信息中直接引用相关的 Azure DevOps 工作项,使用工作项 ID 格式,前缀为 AB(表示 Azure Boards)。例如,在提交信息中添加 AB#206 将链接到工作项 ID 为 206 的工作项。
在另一方向上,你可以点击工作项上的添加链接按钮,并选择现有项,将 GitHub 提交、拉取请求或问题的 URL 链接添加到工作项中。两个系统之间的双向链接提供了编码活动和项目任务、用户故事、缺陷以及在 Azure Boards 中管理的其他工作项之间的完整可追溯性。这种集成提供了一种高效的开发工作流,可以在代码演进时保持进度可视性。
总结
在本章中,我们讨论了将任务跟踪或工单系统集成到 DevOps 工作流中所能带来的巨大价值和好处——无论是在通过 Git 集成实现技术层面的支持,还是在提供工作可视化和组织性方面。
我们考察了一些常见的工具选择,这些工具提供了在 DevOps 流水线中管理任务所需的功能,并为每个系统的入门提供了一个高级工作流。希望这能为你带来洞察和灵感,帮助你通过这些解决方案为开发生命周期带来秩序。为了帮助你的决策过程,以下是每个工具的优缺点简要概述:
| 特性 | JIRA | Asana | Azure 工作项 |
|---|---|---|---|
| 优点 | |||
| 项目管理 | 高级敏捷管理,强大的缺陷跟踪 | 用户友好,适合任务和项目管理 | 综合的敏捷规划,集成 Azure DevOps |
| 定制化 | 高度可定制,适应复杂工作流 | 简单,易于使用,提供基础定制功能 | 高度可定制,支持复杂工作流 |
| 集成 | 与其他 Atlassian 产品的深度集成 | 与包括 Salesforce 在内的各种应用良好集成 | 与 Microsoft 产品和服务的强大集成 |
| 报告功能 | 强大的报告和分析功能 | 基本但易于使用的报告 | 详细的报告、分析和仪表板 |
| 协作 | 适合技术团队,详细的追踪功能 | 非常适合跨职能团队的协作 | 对与微软生态系统深度集成的团队非常有效 |
| 可扩展性 | 适合大规模和复杂项目的扩展 | 适用于各种规模的团队 | 非常适合大型团队,特别是在企业环境中 |
| 缺点 | |||
| 用户界面 | 界面复杂,学习曲线较陡 | 适用于复杂项目管理的功能有限 | 对非技术用户来说可能显得令人不知所措 |
| 定价 | 对大型团队来说可能非常昂贵 | 高级功能需要付费计划 | 可能会很昂贵,尤其是需要额外的 Azure 服务时 |
| 灵活性 | 对简单项目来说可能过于复杂 | 对复杂技术项目来说灵活性差 | 与其他 Azure 服务紧密关联,独立性较差 |
| 初始设置和学习曲线 | 需要时间进行设置和学习,特别是对非技术用户而言 | 入门简单,但扩展性有限 | 需要熟悉微软生态系统 |
| 跨技术团队的协作 | 对非技术团队成员来说不太直观 | 适用于所有类型的团队 | 最适合已经使用微软工具的团队 |
表 8.1 – 工单系统的优缺点对比
在下一章中,我们将介绍 Salesforce DevOps 的另一个核心支柱——备份你的数据和元数据。我们将探讨为什么将两者都纳入强大备份策略是很重要的,并讨论任何备份的有效性都取决于你能否快速且轻松地恢复它。
1362

被折叠的 条评论
为什么被折叠?



