一、 安装Jenkins
- 下载地址:Jenkins
- 打开安装程序:

- 进行到这一步,找到红色地址的密码,输入进去。
- 这是该密码的位置:
- 配置管理员信息。
- 安装完成后,打开系统设置。
- 找到环境变量,配置jdk位置以及sdk位置。
- 这里需要注意的是,ANDROID_HOME、JAVA_HOME和Path这三个Key值不可随意取,按照这个规定配置。这三个环境变量缺一不可,否则后续通过Jenkins打包会发生找不到Jdk、Android sdk等问题。 具体配置的内容和后续配置的电脑中的环境变量配置的一样就行。





具体配置的内容和后续配置的电脑中的环境变量配置的一样就行。
首先右键“我的电脑”->“属性”,打开系统,然后根据下图执行步骤。

7. 下载Unity Plugin插件并且配置。
- 点击系统管理->插件管理,进去后找到Unity Plugin然后下载。
- 下载好之后,点击系统管理->全局工具配置,进去后找到Unity3d,然后点击Add Unity,配置名字和路径。
二、 配置安卓环境。
- 下载并且安装Jdk(http:///jdk-8-windowsx64.zip),
- 下载并且安装SDK,这边推荐去下载Android Studio(自带新版SDK MANAGER),不要去直接去下载SDK Manager,否则会导致SDK Tool版本较低(找不到覆盖更新的方法),间接导致Bat批处理文件导包的时候无法正常导出安卓包(这个问题坑了一天)。主要问题定位于当cmd执行打包的时候,开始对比sdk tools版本,自动执行下一步去更新sdk tools,然而链接不到该更新地址进行自动下载,所以导致异常退出。
- 下载并解压NDK
- 配置电脑环境变量(先配置java环境,后配置安卓环境):
JAVA环境变量参考安卓环境变量参考 - 对Unity配置以上三个环境的路径位置(edit->preference->external tools)
- 推荐使用蓝灯、ss\ssr等代理。
三、 登录Jenkins
- 登录地址: http://localhost:8080/login?from=%2Fmanage
- 管理员账号:xxxxx
管理员密码:xxxxx - 也可以通过create an account来创建一个账号:

四、 新建一个任务
- 选择左侧的“New 任务”,然后输入任务的名字,选择“构建一个自由风格的软件项目”,最后点击“ok”就创建好了一个任务。
五、 任务配置
一般设置

- Description:
项目描述,多人合作请一定要加上。 - Throttle builds:
设置两个build任务之间最小间隔和同一个时间内最大任务数量
Time period可以根据自己的需求选择,分别有:小时、天、周、月、年。 - This build requires lockable resources
这个用的比较少,有一种情况可能会用到 Jekins+Appium 做自动化测试,多台手机的时候,如何让 job 可以自动选取可用设备.
Wiki介绍:使用介绍: - Discard old builds:
该选项配置的是如何抛弃旧的构建。
每次构建相关的文件都会保存下来,将会渐渐耗光磁盘空间,为此提供两种方式供选择(填写数字就行,量词):
- Days to keep builds:如果其值为非空的N,就留N天之内的构建文件,这是以时间为驱动的保留方式。
- Max # of builds to keep:如果#为非空,就公保留最多#个最近构建的相关文件,这是以数量为驱动的保留方式。如果有了新的构建开始,那么最早开始构建的那个任务就会删除。
-高级用法(Advanced): - days to keep artifcts 产品保留时间,但是log,历史记录会保留。
- builds to keep with artifacts 保留最近几个构建的产品。
丢弃化构建:详细参考
- This project is parameterized:
可以设置用户可输入的参数,没有输入则使用默认值,有字符串,多行字符串,布尔值等可以设置。
配置的参数往往是构建允许环境中的一些环境变量。
变量配置之后,往往会在构建的时候要求去输入,比如说提供一个字符串作为版本号的输入等。
这些输入不仅仅单纯的是去给构建的时候增加条件,而是去脚本中传参的时候去用它(根据项目需求去抉择)。


测试输出:


参数化构建:详细参考
- Disable this project:
禁止此任务进行构建,默认是不禁止。
勾选上之后,这个项目将不会有新的构建产生。一般是用于想临时保护项目(以便于不产生构建)这种情况。比如说,你的项目依赖于一些指令(测试服务器,或者源代码库),然后因为这些指令没有搭建好或者没有写好,所以会在一段时间内这个构建不可用。你可以在这个期间内勾选这个选项,这样的话可以避免你的项目去构建一些失败的任务。 - Execute concurrent builds if necessary:
选中此选项后,可以并行执行此项目的多个版本。
这个地方也一般不勾选,一般就是同一个Build触发一次构建的话下一次的构建会等上一次构建结束再进行构建这就是传说中的排队,为了安全考虑,当然如果你同时构建的话不影响可以点击这里比如你参数化那里是不同的测试发布机和发布git地址彼此完全不冲突的话这里可以勾选。
将此项勾选后,可以同时执行,执行在任务自己的workspace上,默认的,使用@来区分不同的工作区,如:@2。详细参考
高级用法(高级一般也用不到)
- Retry Count:
重试次数。
一般我们使用jenkins 从github拉取代码, 然后使用再执行, 但是 免不了github因为服务器配置差, 导致最终拉取失败,然后收到烦人的报警邮件, 这时候就可以去设置这个。 - Quiet period:
构建前等待时间。
配置等待未发生提交变化的时间. 由于 jenkins检测到代码变化时,就自动立即构建,但是有些情况下, 需要多次提交代码到版本控制系统上,此时,可能发生代码还没完整提交就开始构建,造成构建失败,为防止此种情况发生,可以配置值X,则jenkins会在代码变化后等待X秒,如果没在发生代码提交,才开始构建,保证稳定性。
- Block build when downstream project is building:
假如上一个仍在构建过程中,停止本次构建任务。
该选项当多个相关联的项目由一个提交所影响,但是它们必须以一个指定的顺序进行构建的时候非常有用。当你选择这个选项的时候,Jenkins将会在启动这个构建之前,完成任何上游构建Job; 例如使用pipes的时候
- Use custom workspace:
使用自定义工作空间。
Directory:路径,具体配置方法如下。
Display Name:显示的名字,可以不配,默认显示项目名字。 - Keep the build logs of dependencies:
保留依赖项的构建日志。
项目源管理配置
- 进去任务后,找到“Source Code Management”,勾选“Subversion”,在Repository进去任务后,找到“Source Code Management”,勾选“Subversion”,在Repository URL中输入svn地址。
- 在Credentials后点击Add,添加自己的Svn账号和密码。(图下的黄色的地方,往黄黄的username和password中添加用户名字和密码)
- 添加好后,选择自己刚才添加的认证即可。
- Local module directory:svn检出到本机的文件夹路径
- Repository depth:需要检出的文件夹深度,一般设为infinity(配置文件夹下的所有文件,包括子文件夹)具体说明可见插件帮助。
- 在下面的checkout stategy中,有以下几个可以选择的选项以及详细介绍:(以下的更新都会在构建的时候自动运行,所以只选就行了,Jenkins都帮你做好了,网上推荐第四种。)
- Use‘svn update’ as much as possible
- 第一次发布的时候,会把工作目录下的所有文件清空,然后check-out一份完整的项目到工作目录下;
- 以后更新的时候,不会判断已有文件是否在svn里存在。比如工作目录下的文件123在svn里不存在,那么更新的时候不会删除123。
- 不会判断工作目录下的文件是否被改动,只会判断svn是否有新版本需要更新。比如工作目录下的文件zzz.txt内容为zzz,svn上的zzz.txt内容为空,如果svn上zzz.txt没有新版本,则在更新的时候不会更新zzz.txt,也就是说如果手动修改了工作目录下的文件,如果此文件在svn上没有出现新版本,就不会更新。一旦svn上的zzz.txt有新版本后就会更新工作目录的zzz.txt,这时工作目录下会生成如下几个文件:zzz.txt、zzz.txt.mine、zzz.txt.r223、zzz.txt.r224,其中zzz.txt.r223为svn上老版本、zzz.txt.r224为svn上新版本、zzz.txt.mine为工作目录上的zzz.txt的副本、zzz.txt记录了文件变化。
- svn上删除了文件,更新的时候,工作目录里的此文件也会被删除。但是如上例中的zzz.txt手动修改过,已经和svn上的不一样了,这时将不会被删除。
- Alwayscheck out a fresh copy
- 第一次发布的时候,会把工作目录下的所有文件清空,然后check-out一份完整的项目到工作目录下;
- 每一次更新的时候,都会先清除工作目录下的所有文件,然后重新check-out一份完整的项目到工作目录下。
- Emulateclean checkout by first deleting unversioned/ignored files,then ‘svn update’
- 第一次发布的时候,会把工作目录下的所有文件清空,然后check-out一份完整的项目到工作目录下;
- 以后更新的时候会判断工作目录下的文件是否在svn里存在,如果不存在则删除,如果存在且有新版本则更新。
- 会判断工作目录下的文件是否被改动,不管有没有新版本,都会还原为svn上的最新版本。
- svn上删除了文件,更新的时候,工作目录里的此文件也会被删除。
- Use‘svn update’ as much as possible,with ‘svn revert’ before update
- 第一次发布的时候,会把工作目录下的所有文件清空,然后check-out一份完整的项目到工作目录下;
- 以后更新的时候不会判断工作目录下的文件是否在svn里存在。
- 会判断工作目录下的文件是否被改动,不管有没有新版本,都会还原为svn上的最新版本。
- svn上删除了文件,更新的时候,工作目录里的此文件也会被删除。
“build triggers” 构建触发器的配置。
- 下拉找到构建触发器然后配置该选项,之后可以定时或者检查是否有变化来进行自动生成安卓。
- 详细解释一下定时构建语法: “ * * * * * ”
- 第一个*表示分钟,取值0~59
- 第二个*表示小时,取值0~23
- 第三个*表示一个月的第几天,取值1~31
- 第四个*表示第几月,取值1~12
- 第五个*表示一周中的第几天,取值0~7,其中0和7代表的都是周日
- 常用定时构建举例:
由于项目的代码一般存在放SVN中,而一个SVN往往是有多个项目组在提交代码,而每个项目组又有多人组成,其中每个人也都在对自己的那块代码不停地在进行维护,所以说对于一个公司而言,SVN的提交记录往往是很频繁的,正因为如此,Jenkins在执行自动化构建时往往是以天为单位来执行的。 - 下面举的例子就是在一天中常用的定时构建示例。
每隔5分钟构建一次 H/5 * * * *
每两小时构建一次 H H/2 * * *
每天中午下班前定时构建一次 0 12 * * *
每天下午下班前定时构建一次 0 18 * * *
其他的构建方式:
Build after other projects are built:
在其他项目构建完成后再进行构建。

输入的工程就是通过Jenkins创建的项目名称:比如如上图所示的项目名字。
这里又分三种很通俗明了的情况,可以根据实际情况来选择:
①Trigger only if build is stable:其他项目构建成功后触发构建项目
②Trigger even if the build is unstable:其他项目不稳定后触发构建项目
③Trigger even if the build fails:其他项目构建失败后触发构建项目
测试结果:勾选第一项“Trigger only if build is stable”
执行TestOther的构建,然后这个设置了这个项目的构建就会在其成功之后构建,流水线操作。
Poll SCM:
根据SCM软件的版本号,定时检查源码变更。如果有更新,则checkout最新code,然后执行构建动作。
这个的语法和定时构建一摸一样,只是换了规则而已。
例如:*/10 * * * * (每10分钟检查一次源码变化,如果有更新才build)
触发远程构建:

首先输入一个token,然后根据红线所代表的内容,提取Url+token,作为远程构建的链接,根据自己项目是不是带参数选择具体的url。
JENKINS_URL就是你JENKINS页面的地址,如开始说的10.1.3.19:8080
TOKEN_NAME就是刚刚输入完的身份令牌里自己定义的token
最后链接如下所示:
http://10.1.3.19:8080/job/TestOther/buildWithParameters?token=123&HeroVersion=0.01
其中HeroVersion为参数,然后打开就可以自动执行。
对于无参数的JOB,url为:
http://10.1.3.19:8080/job/TestOther/build?token=123
“Bulid Environment配置”

- 在构建开始之前删除工作区:
字面意思很清楚了每次构建之前会把这个job所在的工作区目录里面的东西清空掉再进行构建
#需要插件:Workspace Cleanup(通过点击"系统管理"->“插件管理”->“Available”->“找到对应插件去下载”)
如果不需要高级用法就直接勾选即可实现,高级用法主要是去指定删除那些文件。
- 使用秘密文本或文件
允许获取各种类型的凭据,并从shell构建步骤等中使用它们。 每个绑定都将定义一个环境变量。
#需要插件:Credentials Binding(通过点击"系统管理"->“插件管理”->“Available”->“找到对应插件去下载”) - 如果构建卡住,则中止构建
有些 Job 在执行构建时,由于某些原因导致构建挂起,耗时比较长,而这些长时间挂起的 Job 会导致 Jenkins 内存占用比较大,性能下降,严重的会直接导致 Jenkins 挂掉。所以,我们需要设置构建超时时间来预防这种事情发生,一旦超过一定的时间,要让 Job 自动停止掉。
#需要插件:Build-timeout(通过点击"系统管理"->“插件管理”->“Available”->“找到对应插件去下载”)
上图所需要配置的内容根据以下描述和项目需求去配置。
Time-out strategy (选择以下策略之一:):
Absolute #根据固定的超时中止构建。
Deadline #根据HH:MM:SS或HH:MM(24小时时间格式)中指定的截止时间中止构建
Elastic #定义在杀死构建之前等待的时间,作为最后n次成功构建的持续时间的平均值的百分比。
Likely stuck #当作业比以前的运行时间长许多次时,中止构建。
No Activity #自上次日志输出以来指定的秒数超时。Time-out variable(超时变量):设置构建超时环境变量
Time-out actions:超时发生时执行的操作。 如果没有指定,将使用“中止构建”。
ps:这个超时变量其实就相当于定义一个变量,而其值就代表着上面几种策略中的输入的值,比如:
输出结果为180000毫秒(3分钟):

- 将时间戳添加到控制台输出
#需要插件:timestamps(通过点击"系统管理"->“插件管理”->“Available”->“找到对应插件去下载”)
使得job log的每次输出前面都增加当时的时间,方便查找job里脚本语句运行的间隔时间,方便查找问题。
“build”配置。

- 在“Add build Step”中选择“执行windows 批处理命令。”
- 在“Command”中输入以下指令:
UnityToApk.bat “C:\Program Files\Unity\Editor\Unity.exe” “%WORKSPACE%”
第一个参数“UnityToApk.bat”,Jenkins会自动导向该项目下workspace的UnityToApk.bat。后面详细说。
第二个参数 “C:\Program Files\Unity\Editor\Unity.exe”是往bat文件中传入第一个参数。后面详细说。
第三个参数 “%WORKSPACE%” 是往bat文件中传入第二个参数。后面详细说。
注意:路径最好带引号,因为如果路径有空格,那么命令行将无法识别。
保存。
- 点击“”save“”即可保存。
六、配置项目完成之后可以点击“立即构建”看看是否可以成功构建。

七、检查输出。

八、查看Apk和Build.log。
具体位置在WorkSpace下,如下图所示:

如果发现build失败,可以具体查看下build.log中的输出内容。
九、 批处理文件代码和构建生成代码
- 批处理文件源码:
@echo off
echo 正在生成APK文件...
REM C:\Program Files\Unity\Hub\Editor\2018.2.13f1\Editor\Unity.exe -projectPath D:\Test_Projects\Test2019 -quit -batchmode -executeMethod APKBuild.Build -logFile build.log
%1 -projectPath %2 -quit -batchmode -executeMethod APKBuild.Build -logFile build.log
echo APK文件生成完毕!
pause- 其中%1和%2,就是刚才从Jenkins中传进去的俩个参数,分别是Unity.exe路径和项目路径。只有指定项目路径,才能具体执行构建代码。
- bat是为了执行指定项目路径的构建生成代码。
- 构建生成代码是为了生成apk。
- 需要注意的是该批处理文件需要放在与Assests同级目录下
- 构建生成代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class APKBuild : Editor
{
[MenuItem("Tool/APKBuild")]
public static void Build()
{
BuildTarget buildTarget = BuildTarget.Android;
// 切换到 Android 平台
EditorUserBuildSettings.SwitchActiveBuildTarget(buildTarget);
// keystore 路径, G:\keystore\one.keystore
PlayerSettings.Android.keystoreName = "C:\\Program Files (x86)\\Jenkins\\workspace\\TestHeroDemo\\Assets\\user.keystore";
// one.keystore 密码
PlayerSettings.Android.keystorePass = "123456";
// one.keystore 别名
PlayerSettings.Android.keyaliasName = "bieming";
// 别名密码
PlayerSettings.Android.keyaliasPass = "123456";
List<string> levels = new List<string>();
foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
{
if (!scene.enabled) continue;
// 获取有效的 Scene
levels.Add(scene.path);
}
// 打包出 APK 名
string apkName = string.Format("./{0}.apk", "Test");
// 执行打包
BuildPipeline.BuildPlayer(levels.ToArray(), apkName, buildTarget, BuildOptions.None);
AssetDatabase.Refresh();
}
}- 需要注意的是该代码需要放在Editor目录下面。
















