打 debug 包流程:

  1. git pull 分支最新代码
  2. Android Studio:Build - Generate Signed APK

从 IDE 里可以看到,实际上该操作是执行了 assembleDebug,在打包完成后再将编译目录下的 apk 包安装到调试的手机上并运行。

  1. 拷贝了工作目录下 app/build/outputs/apk 文件夹下的 apk 安装包交付测试

显而易见这些是很枯燥、重复且浪费时间的工作,而一切重复的工作皆可自动化。我们选择使用 Jenkins 这一已经很成熟的持续集成方案来实现自动化打包。

初识 Jenkins

What is Jenkins?

Jenkins is a self-contained, open source automation server which can be used to automate all sorts of tasks related to building, testing, and deploying software.

Jenkins 说白了其实就是后台服务加上 web 管理配置页面。Jenkins 里,每个任务称为 Job,所以简单的说,持续集成的实质就是通过 web 页面构建一个或多个任务,然后通过后台服务持续、自动地执行这些任务。

安装教程

因为 Jenkins 是基于 Java 开发的(但不仅限于构建基于 Java 开发的软件),所以运行 Jenkins 需要配置 Java 环境。

  1. 下载 Jenkins 安装包。Jenkins 下载地址。虽然官方也提供了各个平台的安装包(例如 Mac 端 的 pkg 文件,但个人认为直接下载 war 包自行使用命令安装更为方便)

  1. 在安装包所在目录运行命令:
//默认运行在8080端口
java -jar jenkins.war
//如果报错误为端口号已被占用,先查看端口号(例如8081端口)被什么程序占用
lsof -i tcp:8081
//记住服务的 PID 号(例如8123),强制 kill 相应服务
sudo kill 8123
//或直接指定未被占用端口运行
java -jar jenkins.war --httpPort=2333

Jenkins 就启动成功了。

  1. 浏览器中进入 Jenkins web 配置页面:http://localhost:8081

第一次启动时在控制台会输出一串密钥用于首次登陆验证。当然,如果懒得翻控制台打印出的命令,也可以直接到本地的 Jenkins 安装目录去找(Mac 上一般为 用户目录下的/.jenkins/secrets/initialAdminPassword)。该密钥同时也是 Jenkins 初始账号 admin 的密码。

输入密钥之后会出现如下让用户选择安装插件的选项。如果是第一次接触的同学可能会有点懵。所以这里建议点击右上角关闭,直接进入 Jenkins。后续再根据需求安装插件。

构建 Job

准备工作

成功进入 Jenkins 后,我们就可以开始构建任务啦。但是在此之前,还需要为 Jenkins 配置相应的环境,以及安装需要用到的插件。

安装插件

左侧选择系统管理 - 插件管理 - 可选插件,搜索并安装插件。

必装插件:
  • Gradle Plugin
  • GitLab Plugin
建议安装的插件:
  • build-name-setter (用于自定义每次构建的名字)
  • Build Timestamp Plugin (比较好用的时间戳插件)

tips:如果插件管理里显示可更新、可选插件都为空,前往插件管理 - 高级 - 滑动到最下方的升级站点,将地址替换为http://mirror.xmission.com/jenkins/updates/update-center.json

配置环境

还需要配置一下环境变量,在系统设置 - 全局变量里添加一个 Android Sdk 的目录。

  • ANDROID_HOME = android sdk 所在目录

配置 GitLab 服务器

在配置服务器之前,需要先配置一下证书。

左侧菜单 Credentials - System - Add domain 添加一个证书,Domain Name

输入名字后点击 OK,再点击 adding some credentials 添加有访问代码权限的账户的 token,Kind 栏选择 GitLab API Token,Api token 一栏填入账户的 token,token 的获取方式为 GitLab - User Settings - Private Token。

接着配置一下服务器。左侧 系统管理 - 系统设置,安装 GitLab 插件之后会看到新增了一栏 GitLab,在这里配置一下源码服务器。

Host Url 填写服务器地址:http://xxx.xx.xx.xxx:9000/。

Credentials 选择刚才添加的证书。然后点击右下方的 Test Connection,不出意外的话就可以连接成功了。

添加 SSH

配置好服务器后,还需要配置用于访问服务器的私钥 。SSH 协议规定远程主机在用户发起请求后,会发送一串随机字符串回来,用户使用本地存储的私钥对字符串进行加密后又发送回来,远程主机再使用用户事先配置的公钥比对加密后的字符串,以此来鉴定本次访问是否可信。因此,用于获取源码的服务器上必须配置用于远程登录服务器的 SSH 私钥。

左侧菜单 Credentials - System - Add domain 添加一个证书,Domain Name

输入名字后点击 OK,再点击 adding some credentials 添加有访问代码权限的账户的私钥,Kind 栏选择 SSH username with private key,Private Key 栏有多种方式可选,这里选择直接输入私钥,选择 Enter directly,直接复制私钥内容到输入框中(私钥位置:用户目录/.ssh/ 下的 id_rsa 文件,直接复制文件的所有内容),其他都不用填,点击保存。

构建第一个任务

点击左侧菜单栏 - 新建,新建一个任务

这里看到了两个选项。多配置项目,顾名思义,更适用于有上下游任务、多个项目联动的任务,该项目相比自由风格的软件项目新增了些可选配置,例如上游项目正在构建时阻止该项目构建、使用自定义工作空间等。

我们先选择自由风格的软件项目来试试手。输入项目名后可以看到整个配置页面了。最上方 GitLab connection 一栏选择刚配置的 GitLab。源码管理一栏选择 Git,配置一下项目地址。

Repository URL 填写项目地址:git@git.xxxx.com:xxx/xxxx.。

Credentials 一栏选择之前添加的 SSH。

Branches to build 一栏填写从哪个分支获取,例如从主分支:*/master

配置好之后,滑到最下方应有并保存。之后点击左侧菜单 - 立刻构建试一下吧。如果看到任务被成功构建那就说明已经成功从服务器拉取源码啦。

编译项目

进入 Job,左侧菜单 - 配置,在构建一栏增加构建步骤,选择 Invoke Gradle Script - 选择 Invoke Gradle,并在下方的 Tasks 中配置要执行的命令。比如打测试包命令:

clean
assembleDebug //如果项目中配置了 productFlavors,打包命令需要相应地更换为你需要打包的版本

配置完成后,一样的进入到项目的 app/build/outputs/apk 目录下就可以看到打好的 debug 包。项目位置位于:用户目录/.jenkins/workspace/xxx 。

当然,你也可以自己执行项目的工作目录。在 Job 的编辑页,滑动到最上方, General 选项卡最顶端点击 高级 按钮,可以看到选项:使用自定义的工作空间,例如:

目录:workspace/work/testProject
显示名称:testProject

实现自动化

常见的自动化执行配置方法:进入 Job,左侧菜单 - 配置 - 构建触发器:

定时执行

有两个比较相似的行为:

  • Build periodically :周期性地执行构建
  • Poll SCM :检查源码变更,如果有变更则拉取源码并执行构建

二者都需要在下方的日程表中填写定时规则。

日程表编写规则

简要介绍一下定时编写规则:

  • 规则由5个参数组成,每个参数之间以空格间隔(单个参数里不可以包含空格),例如:* * * * * 。* 号代表忽略该参数。

  • 五个参数从左起分别代表:分(范围0 ~ 59)、时(范围0 ~ 23)、天(范围1 ~ 31)、月(范围1 ~ 12)、星期(范围0 ~ 7,0/7均代表周日)

  • 同个参数可以指定多个数,以英文逗号分隔(注意不要带空格),例如:2,3,5 ;可以指定连续数:2-5(等同于 2,3,4,5)

举几个例子直观地看一下:

H 10 * * *  //每天10点整点。等同于 0 10 * * * ,如果分的参数输入0,会建议你使用 H 替代。

20 8,10,18 * 11,12 1-4 //11、12两个月的周一到周四的每天8点20、10点20、18点20。

GitLab Hook

构建触发器选择:Build when a change is pushed to GitLab. GitLab CI Service URL: http://localhost:8081/xxx/xxx

这个需要在 GitLab 的源码项目里配置一下上面提到的地址,这样源码在接收到 push 事件时会通知 Jenkins 执行构建。因为没有将 Jenkins 发布到外网,所以可以看到上面提供的 hook 的地址也只是个本地的 localhost 的地址,填写这个地址外网是无法通知到的。这里暂时没有测试该特性。

基于上游项目的构建

构建触发器选择:Build after other projects are built。并填写上游项目的 Job 名称。还可以基于上游项目的构建情况,是否成功、失败来构建自身。

基本上这些操作已经可以使整个自动化打包流程运行起来了。

关闭服务

采用 Jenkins CLI的方式来关闭Jenkins。

左侧菜单 - 系统设置 - Jenkins CLI。下载 jenkins-cli.jar 之后,通过使用命令控制 Jenkins,例如:

java -jar jenkins-cli.jar -s http://localhost:8081/ shutdown //关闭 Jenkins 服务

如果执行该命令时报没有权限的错误,则需要为 admin 账号配置一下权限。

另外网络上很多提到直接在链接后加上相应的操作,例如 exit、restart、reload等,例如访问 http://localhost:8081/exit 代表退出 Jenkins,但估计很多人会遇到一下问题:

此类跳转失败的错误原因是 Jenkins 在 http 请求头部中放置了一个名为.crumb的token,在使用了反向代理,并且在设置中勾选了“防止跨站点请求伪造”之后此

token 会被转发服务器认为是不合法头部而去掉,导致跳转失败。解决方法就是左侧菜单 - 系统管理 - Configure Global Security 中取消勾选 防止跨站点请求伪造

权限配置问题

如果因为设置错误而收回了配置权限,导致 admin 账号连主页都无法进入,解决的方法就是直接到 Jenkins 安装目录里修改配置文件。

进入安装目录(用户目录/.jenkins)/config.xml,修改 useSecurity 栏目,修改为任何用户可以做任何事:

<useSecurity>true</useSecurity>
<authorizationStrategy class="hudson.security.AuthorizationStrategy$Unsecured"/>
<securityRealm class="hudson.security.HudsonPrivateSecurityRealm">
<disableSignup>true</disableSignup>
<enableCaptcha>false</enableCaptcha>
</securityRealm>

展望

以上的自动化打包流程实际上还有可以改进的地方,例如每次测试人员都需要从 Jenkins 服务器上拷贝 apk 安装包,这一流程也应该自动化实现,比如使用脚本自动将 apk 安装包上传至公司 FTP 服务器,或者上传至第三方软件分发服务商,例如蒲公英、Fir 等,还可以将下载地址转换为二维码显示在相应的 Job 页,测试人员直接扫码安装即可。

以及 Jenkins 的其他功能的扩展,例如构建发生错误时自动将日志发送至相关开发人员的邮箱,使开发人员可以更快更及时地响应问题。

以及如果项目有编写单元测试,可以使用 Jenkins 周期性地自动运行单元测试,及早发现新引入的问题。

Jenkins 是一个工具,同时也代表着一种思想,它告诉了我们:

懒是第一生产力 :P。

以上。

Jenkins 持续集成实现 Android 自动化打包的更多相关文章

  1. Jenkins持续集成企业实战系列之Jenkins插件下载及邮件配置-----05

    注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.    最初接触Jenkins也是由于公司需求,根据公司需求Java代码项目升级的.(公司是 ...

  2. 自动化打包 Jenkins 持续集成 Git Gradle MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  3. Docker+Jenkins持续集成环境(5): android构建与apk发布

    项目组除了常规的java项目,还有不少android项目,如何使用jenkins来实现自动构建呢?本文会介绍安卓项目通过jenkins构建的方法,并设计开发一个类似蒲公英的app托管平台. andro ...

  4. Linux-GitLab+Jenkins持续集成+自动化部署

    GitLab+Jenkins持续集成+自动化部署 什么是持续集成? (1)Continuous integration (CI) 持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个 ...

  5. CentOS 7 Gitlab+Jenkins持续集成+自动化部署

    基于上次的环境<部署Gitlab+Jenkins持续集成环境> 来实现自动化部署 系统管理–>插件管理–>安装以下插件: Credentials Plugin(默认已经安装) ...

  6. .NET持续集成与自动化部署之路第一篇——半天搭建你的Jenkins持续集成与自动化部署系统

    .NET持续集成与自动化部署之路第一篇(半天搭建你的Jenkins持续集成与自动化部署系统) 前言     相信每一位程序员都经历过深夜加班上线的痛苦!而作为一个加班上线如家常便饭的码农,更是深感其痛 ...

  7. 接口自动化平台搭建(四),自动化项目Jenkins持续集成

    一.Jenkins的优点 1.传统网站部署流程   一般网站部署的流程 这边是完整流程而不是简化的流程 需求分析—原型设计—开发代码—内网部署-提交测试—确认上线—备份数据—外网更新-最终测试 ,如果 ...

  8. 自动化项目Jenkins持续集成

    一.Jenkins的优点 1.传统网站部署流程   一般网站部署的流程 这边是完整流程而不是简化的流程 需求分析—原型设计—开发代码—内网部署-提交测试—确认上线—备份数据—外网更新-最终测试 ,如果 ...

  9. 手把手教你利用Jenkins持续集成iOS项目

    前言 众所周知,现在App的竞争已经到了用户体验为王,质量为上的白热化阶段.用户们都是很挑剔的.如果一个公司的推广团队好不容易砸了重金推广了一个APP,好不容易有了一些用户,由于一次线上的bug导致一 ...

随机推荐

  1. I/O中的 同步异步,阻塞非阻塞

    I/O中的同步和异步的概念和线程中不太一样. I/O写的时候,默认是写到页高速缓存就返回的,然后异步刷到磁盘上.而同步的I/O指的是改动写到磁盘上之后才会返回结果.可以通过fsync(),和fdata ...

  2. Clickhouse 入门

    clickhouse 简介 ck是一个列式存储的数据库,其针对的场景是OLAP.OLAP的特点是: 数据不经常写,即便写也是批量写.不像OLTP是一条一条写 大多数是读请求 查询并发较少,不适合放置先 ...

  3. JVM(四)-虚拟机对象

    概述: 上一篇文章,介绍了虚拟机类加载的过程,那么类加载好之后,虚拟机下一步该干什么呢.我们知道java是面向对象的编程语言,所以对象可以说是java'的灵魂,这篇文章我们就来介绍 虚拟机是如何创建对 ...

  4. SpringBoot集成FastDFS依赖实现文件上传

    前言 对FastDFS文件系统安装后的使用. FastDFS的安装请参考这篇:Docker中搭建FastDFS文件系统(多图) 本文环境:IDEA + JDK1.8 + Maven 本文项目代码:ht ...

  5. JZOJ2020年9月5日提高组反思

    JZOJ2020年9月5日提高组反思 T1 考试的时候没有头绪,就打了个暴力,愉快的拿到了10分的\(impossible\) 正解是\(DP\),设\(f[i][j][k]\)表示地\(i\)种币值 ...

  6. 第4.7节 Python特色的序列解包、链式赋值、链式比较

    一.序列解包 序列解包(或可迭代对象解包):解包就是从序列中取出其中的元素的过程,将一个序列(或任何可迭代对象)解包,并将得到的值存储到一系列变量中. 一般情况下要解包的序列包含的元素个数必须与你在等 ...

  7. 第11.6节 Python正则表达式的字符串开头匹配模式及元字符“^”(插入符、脱字符)功能介绍

    符号"^"为插入符,也称为脱字符,在Python中脱字符表示匹配字符串的开头,即字符串的开头满足匹配模式的要求.这个功能有点类似搜索函数match,只是这是通过搜索模式来指定,而m ...

  8. PHP 的$server变量

    PHP中$_SERVER["QUERY_STRING"]函数   详解PHP中$_SERVER函数的QUERY_STRING和 $_SERVER存储当前服务器信息,其中有几个值 如 ...

  9. pandas 处理缺失值(连续值取平均,离散值fillna"<unk>")

    # 2.1处理缺失值,连续值用均值填充 continuous_fillna_number = [] for i in train_null_ix: if(i in continuous_ix): me ...

  10. Day6 Scrum 冲刺博客

    一.站立式会议# 1. 会议照片 2. 工作进度+燃尽图  团队成员 昨日完成工作  今日工作计划 遇到的困难  周梓波  将方块旋转变形  添加键盘监听事件  不熟悉监听事件的操作  纪昂学  左右 ...