1
由于本人没有接触过使用Jenkins进行版本构建相关的内容,最近的项目里正好负责了,所以在此记录,做个备忘。和学习。
版本机安装Jenkins,启动Jenkins服务,创建管理员账户,然后登陆。
2
在这里首先在Unity中为版本构建创建一个构建脚本,并且声明一个方法,作为入口,作为Jenkins静默启动Unity进程并且要调用的函数。
/// <summary>
/// 出包函数入口
/// </summary>
[MenuItem("构建版本")]
private static void Build()
{
//...
}
然后在Jenkins配置中,我将构建流程划分为了Pipeline的几个阶段,分别是:
- Clean:移除版本机项目内的新文件(unversioned files),这类一般是生成的meta文件,或引擎自己生成的一些别的文件,并且revert所有的变更,让版本机项目保持干净状态。
- Pull:拉取最新版本到版本机本地。
- Revert:如果有需要,则回退到指定版本,在指定版本进行打包。
- GetVersion:获取当前的版本号以参与构建。
- SetBuildMode:通过一些参数自定义构建。
- Build:构建。
- Notification:通知构建完成。
Jenkins使用Groovy脚本声明Pipeline,语法如下
//要处理的SVN目录
def SVN_PATH = 'X:\\your_unity_project'
pipeline
{
stages
{
//使用stage声明一个pipeline阶段
stage('Clean')
{
//...
}
stage('Update')
{
//...
}
stage('Revert')
{
//也可使用when+expression来表示条件,以条件地执行某些阶段
when{
expression{
//...
}
}
//...
}
stage('GetVersion')
{
//..
}
stage('SetBuildMode')
{
//..
}
stage('Build')
{
//...
}
stage('Notification')
{
//...
}
}
}
接下来摘取一些stage来做说明。
3
Jenkins支持在部署的机器上执行批处理,可以利用这点对版本机项目进行更新,以SVN为例。
-
Clean:
stage('Clean') { steps { //调用来利用SVN命令行的方式清理项目 bat "svn cleanup ${SVN_PATH} --remove-unversioned --remove-ignored" bat "svn revert -R ${SVN_PATH}" } }
其他stage如revert,update同理,只要调相应的svn命令即可。
-
Revert:
假如我想要回退到特定版本进行构建,在这种情况下,需要一个参数来表示回退到哪个版本。
在构建触发器中添加一个字符参数,SVNVersion,并且将他的默认值设置为0.
在对应的条件stage中,可以这样使用
stage('SvnRevert') { when { //当SVNVersion不为0,执行该stage expression { SVNVersion != '0'} } steps{ //回退到指定版本 bat "svn update -r ${SVNVersion} ${SVN_PATH}" } }
-
SetBuildMode:如果想要通过一些参数来自定义构建流程,或者让其影响pipeline逻辑的话,则需要一些额外参数。
可以通过在构建触发器中添加一些参数,或者在流水线脚本中声明一些参数的方式来实现,以我的为例以做参考。
BuildMode,PackageDebugMode,IsOnlyBuildApp,IsForceRebuildAB,BuildTarget,IsBuildRelease
他们的含义分别如下
//触发器添加参数: //BuildMode:构建模式,构建分包还是整包 //PackageDebugMode:构建调试模式 //SVNVersion:要回滚的版本 //IsOnlyBuildApp:是否仅构建APP //IsForceRebuildAB:是否强制重新构建AssetBundle,因为引擎默认增量打包 //BuildTarget:构建的目标平台,Windows/Android/iOS //IsBuildRelease:是否构建发行版 //在流水线中,如果想要使用他们,先在groovy脚本开头声明 def BUILD_PARAM = "${BuildMode}" def IS_ONLY_BUILD_APP = "${IsOnlyBuildApp}" def IS_FORCE_REBUILD_AB = "$IsForceRebuildAB" def BUILD_ARGS = "" def BUILD_TARGET = "${BuildTarget}" def IS_BUILD_RELEASE = "${IsBuildRelease}"
以SetBuildMode stage为例,我这样处理:
stage('PackageModeParse') { steps{ script { //可以像java/C#那样在groovy中声明一个stringBuilder用以组合构建参数 //在构建脚本中添加对应的参数 def builder = new StringBuilder("PackageDebugMode") if (PackageDebugMode == 'VSDebug') { builder.append("-VSDebug") } else if(PackageDebugMode == 'MonoPDB') { builder.append("-MonoPDB") } else if(PackageDebugMode == 'DeepDebug') { builder.append("-DeepDebug") } else { builder.append("-Normal") } //添加上面声明的参数 builder.append(" IsOnlyBuildApp-").append(IS_ONLY_BUILD_APP) builder.append(" IsForceRebuildAB-").append(IS_FORCE_REBUILD_AB) builder.append(" BuildTarget-").append(BUILD_TARGET) builder.append(" IsBuildRelease-").append(IS_BUILD_RELEASE) //将参数输出到BUILD_ARGS BUILD_ARGS=builder.toString() echo BUILD_ARGS } } }
然后可以通过命令行传入到构建脚本中,参与构建逻辑
stage('BuildFull') { steps { bat """ ${UNITY_PATH} -projectPath ${PROJECT_PATH} -executeMethod your_project.Editor.ProjectBuild.Build ProjMode-FULL ${BUILD_ARGS} -quit -batchmode -logFile "${PROJECT_PATH}/Reports/Build/JenkinsBuildLog.txt" """ } }
以静默方式启动unity,传入项目路径。
executeMethod可以调用指定方法,之后传入自定义参数
-logFile输出编辑器的日志文件,方便查看
unity的命令行参数,可以查看文档:https://docs.unity.cn/cn/2019.4/Manual/CommandLineArguments.html
在构建脚本中,可以这样获取命令行参数
/// <summary> /// 获取jenkins构建参数,是否构建发行版 /// </summary> public static bool IsBuildRelease() { //使用System.Enviroment.GetCommandLineArgs()获取命令行参数 foreach (string arg in System.Environment.GetCommandLineArgs()) { if (arg.StartsWith("IsBuildRelease")) return true; } return false; }
大致流程就是如此,之后就是构建项目的逻辑了,比如收集资源,构建资源,构建播放器等等,就不多说了。
补充,经群里大佬指点,给了几个建议:
1、可以考虑全用python做,因为要考虑跨平台,ios用sh,win上bat的,要维护的就多,即使是shell也有很多命令不好写。
2、参数最好是用调用函数的方式,去获取命令行参数的,后续单机写起来麻烦,或者从能单机出包之后,再往Jenkins上挪。
后续:添加了SideLinked Bar,自定义侧边栏,可以配置下载构建日志 / 包体