Salesforce学习之路-developer篇(二)利用Jenkins和Bitbucket实现Salesforce的CI/CD功能
上文提到,基于CRM的二次开发是必不可少的,但是在实际项目中CI/CD是不可忽略的一个重要部分,与传统的Java,Python项目不同,如果对Salesforce进行持续集成和持续部署呢?
结合找到的各种资源,并加上之前Java和Python的CI/CD经验,这里设计了一套简单的模版,如有错误,望各位大佬斧正。
1. 系统结构图
这里的设计,主要利用了Ant的代码迁移功能。
详细知识可参考:https://developer.salesforce.com/docs/atlas.en-us.daas.meta/daas/meta_development.htm
2. Jenkins配置
这里选择构建一个自由风格的软件项目
2.1 源码管理
这里选择Git,找到对应的Git库,然后clone其HTTP的链接,将其复制至Repository URL
2.2 创建凭据
创建凭据时,你可以在Credentials后面点击Add按钮,然后选择对应的项目库,输入用户名和密码,cs-jenkins.gen/******。
注意:这里添加的凭据仅适用于该item,如果想要创建一个全局的凭据,需要在Jenkins项目的凭据栏添加全局凭据。当然添加的方式有多种,最常用的便是用户名/密码与公钥/私钥方式,如果感兴趣可以自行查阅相关资料。
2.3 Git添加用户权限
【Repository Setting】 --> 【Repository Permissions】 --> 【User access】
点击git库设置(左下角 ),然后点击库权限,添加可访问用户cs-jenkins.gen
注意:除了添加单个用户外,还可选择添加某个用户组,选择Group access即可。
2.4 构建触发
接触过Jenkins的都知道,它有多种触发方式,但业内常用的方式一般为两种:定时器和轮询SCM。
定时器:顾名思义,每隔一段时间便从Git上拉取代码,然后触发构建。
轮询SCM:每隔一段时间,便向Git发送查询信息,查看指定分支代码是否改变,如果不变则跳过,如果代码变化,则触发构建。
这里选择轮询SCM,并且设置每隔五分钟便向Git查询一次(时间太长,会导致CI不及时;时间太短,调用API过于频繁造成性能损耗)
2.5 构建
构建模块,是jenkins的核心,不同于Java的Mvn打包的构建方式,这里采用Invoke Ant,直接将Sandbox1的代码迁移到Sandbox2中。
这里分为两步:ant迁移代码,将Jenkins工作空间代码提交至Git
- Invoke Ant
关于ant在salesfroce中是如何做到代码迁移的,请参考:https://developer.salesforce.com/docs/atlas.en-us.daas.meta/daas/meta_development.htm
build.xml
<project name="Code Backup Without Folders" default="retrieve" basedir="." xmlns:sf="antlib:com.salesforce"> <property file="build.properties"/> <property environment="env"/> <taskdef uri="antlib:com.salesforce" resource="com/salesforce/antlib.xml" classpath="ant-salesforce.jar"/> <target name="deploy"> <sf:deploy username="${Sandbox2.username}" password="${Sandbox2.password}" serverurl="${sfProduction.serverurl}" deployRoot="${Sandbox2.retrieveTarget}" runAllTests="true" /> </target> <target name="retrieve"> <git command='checkout' dir=""> <args> <arg value="${git.release}" /> </args> </git> <git command="remote" dir=""> <args> <arg value="set-url" /> <arg value="origin" /> <arg value="https://${git.userName}:${git.password}@bitbucket/scm/cs-digitalization/sp.git" /> </args> </git> <git command="pull" dir="" /> <sf:retrieve username="${Sandbox1.username}" password="${Sandbox1.password}" serverurl="${sfSandbox.serverurl}" retrieveTarget="./" unpackaged="package.xml"/> <echo message="Commiting all changes with message ${git.commitMessage}" /> </target> <macrodef name="git"> <attribute name="command" /> <attribute name="dir" /> <element name="args" optional="true" /> <sequential> <echo message="Executing Command in folder @{dir}" /> <echo message="git @{command}" /> <exec executable="git" dir="@{dir}"> <arg value="@{command}" /> <args/> </exec> </sequential> </macrodef> </project>
- Execute Shell
if [ -n "$(git diff)" ] then git add . git commit -m "Commiting all changes with message from Sandbox" git remote set-url origin https://cs-jenkins.gen:******@bitbucket/scm/cs-digitalization/sp.git git push -u origin release/dev else echo "Nothing changed" fi
3. FAQ
虽然上述流程并不复杂,甚至可以说是比较简单,但是在其中也着实踩了几个坑,这里简单提下遇到的问题以及解决的方案。
3.1 Problem: failed to create task or type antlib:com.salesforce:retrieve
原因:由于本人用的jenkins是公司提供的平台,是由多个实例组成的集群,所以每次触发时并不在某台固定的VM上,并且本人没有直接访问服务器的权限。说来可能运气比较差,遇到的几台VM上都没有成功装ant-salesfroce.jar包,故手动下载ant-salesforce.jar包,并上传是代码工程中,这样不管在哪台VM工作,在向Git拉取代码时,并会拉取该Jar包(22.6M)。当然,这是会增加拉取代码时间,所以若有访问Jenkins服务器权限的话,建议在服务器中直接安装。
解决方案:
1)下载ant-salesforce.jar包,并上传至代码工程。
下载链接:https://gs0.salesforce.com/dwnld/SfdcAnt/salesforce_ant_46.0.zip
2)build.xml中重定义依赖包位置。
<taskdef uri="antlib:com.salesforce" resource="com/salesforce/antlib.xml" classpath="ant-salesforce.jar"/>
3.2 Problem: could not read Username for 'https://bitbucket.com': No such device or address.
原因:虽然在jenkins中源码管理的地方配置了凭据,但这只用于链接,在提交时并没有使用该用户,所以相当于匿名提交,这是Git所不允许的。
解决方案:手动设置git的remote url,并在url中显式配置用户名和密码。
git remote set-url origin https://cs-jenkins.gen:******@bitbucket/scm/cs-digitalization/sp.git
这样,一个基于Jenkins的Salesfroce CI/CD便完成了。上述若有模糊或错误之处,还望各位不吝之处,抱拳了。
- Salesforce学习之路-developer篇(三)利用Visualforce Page实现页面的动态刷新功能
- 利用jenkins实现CI/CD的自动、持续构建及测试软件
- IOS开发---菜鸟学习之路--(十五)-如何实现拍照功能
- C++学习之路—多态性与虚函数(一)利用虚函数实现动态多态性
- IOS开发---菜鸟学习之路--(十五)-如何实现拍照功能
- jenkins实现CI/CD
- 【学习ios之路:UI系列】获取ios系统版本的相关操作. 及 将汉字转化为拼音功能实现
- jQuery学习之路(7)- 用原生JavaScript实现jQuery的某些简单功能
- 【学习ios之路:C语言】小程序:实现类似ATM取款机功能.
- python学习之路之案例1(修改haproxy的配置文件,并实现下线、上线的功能)
- salesforce 零基础学习(四十四)实现checkbox列表简单过滤功能
- C++学习 【4.2】 利用函数实现指定的功能---函数的调用
- Android学习——自定义利用Scroller实现可循环滚动的动画菜单控件(功能完善待改进)
- xml学习(三)---利用xml文件实现数据岛功能(网页显示xml文件中的内容免C#代码操作xml文件)
- osgi实战学习之路:5.生命周期及利用命令、装饰者模式实现基于socket交互Bundle命令demo
- IOS开发---菜鸟学习之路--(九)-利用PullingRefreshTableView实现下拉刷新
- python学习之路之案例0(实现登录功能,登录错误次数超过3次,自动退出登录)
- 【CI学习笔记】利用jquery中的ajax,调用接口,实现登录
- C++学习 【4.3】 利用函数实现指定的功能---内置函数
- [原创]java WEB学习笔记89:Hibernate学习之路-- -Hibernate检索方式(5种),HQL介绍,实现功能,实现步骤,