我是怎么慢慢变懒的 : Jenkins + 蒲公英

封面图片来自google

关于懒惰

经常看到很多博文里面讲’懒惰’是一个优秀程序猿的良好品质,这一点我深以为然,因为在程序猿的工作中总是充满了重复劳动,也许正是因为这个原因,导致大部分程序猿慢慢变得懒惰,而那些没变懒的程序猿他们慢慢灭绝了~~~。而对于懒惰这个词,我们不能曲解它的意思,并不是怠倦、消沉的对待工作,而是当一个程序员遇到重复的工作时,懒惰的程序员首先想到的是我要开发出一个工具自动执行这些工作。

为什么需要工具

当 UI 妹子给你一大堆图片而没有给你加上 @2x 后缀时,看着妹子可怜的眼神,怎么忍心让妹子们返工,懒惰的程序员就在想了,这特么是一个循环重复的劳动,为啥不写个脚本自动给每张图片文件名加上一个 @2x 后缀呢,分分钟搞定,然后准时下班约会去了。。。。

所以很早之前我的第一个开源工具 dSYM 分析工具 就是这么来的,当我连在命令行中续修改了几个友盟统计后台收集到异常后,我发现这就是一个重复而且繁琐的劳动啊,所以我便花了两个多小时做了一个 APP 应用,这样以后我每次需要做的只是:1)打开应用,2)拖入 dSYM 文件 3)输入异常地址,便得到异常信息了。

而写这篇文章则讲述了我是如何一步一步从 1)手动打包 –> 2)Jenkins 打包,手动发布 –> 3)Jenkins 打包 + 蒲公英 分发 的。

起因

对于发包这个问题,相信是每个程序猿哥哥心中挥之不去的痛,而测试妹子们也在每次马上就发的承诺中得出一个结论 : “你是个大骗子”。

所以每次被测试妹子追着要测试包,产品经理说给我装一个开发中的新版本瞧瞧呗,后台哥哥说给我安装一个某某老版本的包调试一下啊。。。然后每次不得暂停下手中的工作,切换到某个版本,Archive。。。。终于有一次答应测试妹子吃饭前会给他们发包后,忙着忙着就忘掉直接去吃饭了,看着妹子 QQ 上发来各种鄙视的表情,这不是我想要的人生啊,我一定要改变在测试妹子心中的形象,所以自动化构建这件事情提上日程.

使用 Jenkins 半自动化

我直接选用了已经很成熟的 Jenkins 持续集成解决方案,至于如何配置就不做过多介绍了,网上有不少这类的文章。有了 Jenkins 后,给我带来最便利的一点就是,每次打包的时候,直接在公司的 Mac 服务器上进行操作,而我还可以继续进行手上的工作,打包完成后把 ipa 包发给测试,同时也教会了测试如何从 Jenkins 上下载已经打包好的 ipa 文件,就这样我可以随时在手机上打开公司内网的 Jenkins 打包,当我把这一切告诉测试妹子的时候,她用期望的眼神看着我说:“这是真的么。。。”

Jenkins + 蒲公英 升级

就这样用了一段时间,也没遇到什么问题,或许是比较爱折腾,我发现每次 Jenkins 打包好了之后,我还需要手动去下载,或者让测试他们下载,当测试拿到文件后,还需要将手机连到电脑用 iTunes 或者第三方工具安装文件,我想要是 Jenkins 打包完成后会自动通知测试更新并安装该多好,而且之前也听说过第三方的分发平台 “蒲公英”,于是我去蒲公英网站看了一番,很高兴的是他们开放上传 APP 和安装 APP 等 API,有了这个东西,我的想法便完全可以实现了:1)Jenkins 打包 2)打包成功后 IPA 文件上传到 Tomcat 服务器 3)通过 API 把 IPA 文件传给 蒲公英 4)上传成功后把安装地址通过邮件发送给测试。 5)测试直接在手机上打开地址安装。
流程图大概像这样:图片

1.IPA 文件上传到 Tomcat 服务器

由于每次 Jenkins 打包的时候,编译后的文件是放在项目根目录下的 build 文件夹里面,每次 build 的时候这个文件夹内的文件都会被覆盖,所以每次 build 后我都会通过 FTP 把 IPA 文件上传到 Tomcat 上备份,同时还可以方便提供给别人下载,比如在给测试发送蒲公英的安装地址时,同时也可以给出 IPA 下载地址。

* 开启 Mac FTP-server

Mac 电脑本身是支持 FTP 服务的,只不过系统默认关闭了,Mountain Tweaks 这款软件可以很方便的修改系统的一些设置,比如是否开启打开 Window 动画,是否显示用户的 Library 文件夹,其中有一个选项就是是否开启系统的 FTP-server 功能。图片

* 配置 Jenkins 的 FTP Server

Mac服务器支持 FTP-server 后,我在 Jenkins 上安装了 Publish Over FTP Plugin 这个插件,这个插件可以将指定的文件发送到选中的 FTP 服务器上去,安装完插件后,在 Jenkins 的系统设置中会多出一项 Publish over FTP 的设置,因为 Tomcat 和 Jenkins 是在一台电脑上,所以 Hostname 直接指向本地,Remote Directory 也直接指向 Tomcat 的 webapps 下对应 app 的目录。配置好后可以点 Test Configuration 测试一下,如果显示 success,则成功了。
图片

* 在 Job 的设置里面指定上传到 FTP 的文件

Jenkins 配置好 FTP Server 后,接下来就需要在 Job 中去设置打包成功后把哪些文件上传到指定的 FTP Server 中去了。在 增加构建后操作步骤中 有一个 Send build artifacts over FTP 选项,这里首先需要选择我们之前配好的 FTP Server。Source files 是我们构建目录下 build 文件夹内所有的文件,Remove prefix设置为 build 是告诉插件创建路径的时候不要包含 build,Remote directory则是我们指定的 FTP Server 上需要创建的目录,这里我以 Jenkins 构建的版本号去创建文件夹,之后取文件的时候,路径便会很方便拼接。
图片

2.通过 API 把 IPA 文件传给 蒲公英

打包成功了,并且文件也备份到 Tomcat 上去之后,接下来就需要编写脚本了,脚本需要的功能是:1)上传 IPA 文件到 蒲公英 2)发邮件通知测试。这两点通过脚本是很好实现的,已经放在 GitHub 上,如果想将脚本应用到自己的环境中,最主要的是如下这几行代码 :
图片

uKeyfile_name_api_keyinstallPassword这四个值是根据自己的情况配置的。project_name的值很重要,涉及到很多地方:1)tomcat 的 webapps 目录下面要有 project_name 对应的目录,因为在获取 ipa_file_tomcat_http_url 的时候,是需要 project_name的, 还有就是获取发给蒲公英的 IPA 文件时也需要知道 project_name

接着就需要让 Jenkins 去执行这个脚本了,通过对 Jenkins 插件的搜索,找到一个叫 Post-Build Script Plug-in 的插件,功能官方介绍写的很清楚:PostBuildScript makes it possible to execute a set of scripts at the end of the build.
安装完这个插件后,在 Job 的 增加构建后操作步骤 中会多出一个 Execute a set of scripts 的选项,这里我只配置了 Build steps 中的 Execute shell,让它用 Python编译器去执行项目根目录下的脚本,还有就是 Execute script only if build success 勾选上:
图片

这样当 Jenkins 打包成功后,便会执行此脚本,最终达到了我的目的。

最终收到的邮件大概是这样的:

图片

如果是在手机上打开邮件的话,可以直接使用第三种方式:点我直接安装,这种方式最方便,其次是第二种,蒲公英在线安装,最后一种便是自己下载 IPA 包到本地,使用工具安装。

到这儿之前设想的都已经实现了,整个过程中从开发的角度来说,需要的只是点击一下 Jenkins 中的 立即构建 按钮,然后就继续做手头上的事情把!

总结

教科书上把会不会制造工具当做人和动物的根本区别,我觉得这也是判断一个好程序员的标准之一,优秀的程序员总是会去寻找好的工具,或者自己去创造一些工具来提高自己的生产效率,他们通过工具把那些浪费在重复劳动上的时间花在了更有意义的事情上去。

任何工具出现的最初目的都是为了提高生产效率,很庆幸在 iOS 开发的这个圈子中有一大批的先驱者,他们创造并开源了很多优秀的工具,为这个环境奠定了一个良好的基础,所以在工作或生活中,多创造工具,让自己变得更懒,却更有价值!

  • Pingback: madelyn marie porn

  • Pingback: molodezhka4sezon212223seriya

  • Pingback: molodezhka4seria

  • Pingback: lyutsife2sezon7seriya8910vse

  • Pingback: Молодежка 4 сезон 15 16 серии

  • Leemon

    文章里的图片是本来就没有呢还是没有出来呢

    • answerhuang

      是因为百度的文件存储服务迁移了,之前一直没时间弄,上午抽了点时间弄好了。

  • malaimo feng

    需要收集UDID,这个最不爽

    • dealstoday

      文章里的图片是本来就没有呢还是没有出来呢
      1birthdaygreetings. com/

  • summer

    又不能偷懒点个赞了 只能打字了。。。

  • hongchao

    多谢楼主分享,赞楼主的折腾精神。

  • 羊宏飞

    多谢楼主 正解决了我的问题~

  • jay-egg

    很感谢 楼主分享,很受益

  • http://akring.github.com Akring

    想咨询一下,我的项目文件结构是:

    最外层文件夹==>内层文件夹==>两个项目文件

    使用Jenkins进行build的时候都会报错

    而这种文件夹套文件夹的结构是无法修改的,是不是我基本上就告别Jenkins了。。。

    • answerhuang

      怎么会呢,你指定 Xcode Workspace File 或者 Xcode Schema File 的时候,用全路径啊。

      • http://akring.github.com Akring

        新手没用过jenkins,网络上搜索到的教程都不太详细,有几个点想要请教一下你:

        1、我的项目比较大,使用git做版本控制,如果每次jenkins都从git服务器pull下来build的话非常费时间,所以想让jenkins直接build本地的项目文件,不知道是否可行(网络上大多都是基于svn的教程)。

        2、指定 Xcode Workspace File 或者 Xcode Schema File 的时候,会出现“error 13 permission denied”的报错,同样找不到相关的解决方法,报错如下:

        ( FATAL: Cannot run program “/usr/bin/xcodebuild” (in directory “/Users/akring/DeskTop/miicaa_ios/Code”): error=13, Permission denied)

        不胜感激

        • answerhuang

          1. jenkins 从 git 上只会 pull 本地没有的东西,只要你不要清理工作空间,如果有新的 commit,只会更新那几个没有的 commit,并不会重新pull。
          2. 麻烦检查一下 xcodebuild 有没有可执行权限。

          • http://akring.github.com Akring

            好的,非常感谢

  • adu

    请问我用workspace工程测试问什么报错?
    PhaseScriptExecution Copy Pods Resources /Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/ECadillac-gbzqwzovvepagsevaqtcfnrsfqko/Build/Intermediates/ArchiveIntermediates/ECadillac/IntermediateBuildFilesPath/ECadillac.build/Release-iphoneos/ECadillac.build/Script-03822F8C439484A8009CD0A5.sh
    (1 failure)
    FATAL: Build directory does not exist at /Users/Shared/Jenkins/Home/jobs/ECadillac/workspace/build/Release-iphoneos. Potential configuration issue.
    Build step ‘Xcode’ marked build as failure

    • answerhuang

      检查一下 Xcode 构建步骤里面 General Build Settings 里面的 Output directory 有没有设置,我的是 ${WORKSPACE}/build/

      • adu

        每次都是build执行脚本文件的时候报错

      • adu

        每次都是build执行脚本文件的时候报错…

      • adu

        每次都是build执行脚本文件的时候报错,如图

        • answerhuang

          看最后一行,是权限问题,是不是脚本里面什么操作没有权限。

          • adu

            那怎么解决呢,我的账户是管理员账户啊

          • adu

            脚本是cocospod生成的,应该是这句copy的执行没有权限,如图

          • answerhuang

            cocospod 好像没这个脚本吧,你可以把可能涉及到的目录权限都设为 everyone 可读写试试。

          • adu

            应该都有吧,我是新建了个测试工程,新加的pod,我试试楼主的方法

          • adu

            我把权限改了就可以了,多谢楼主

          • answerhuang

            你可以到 jenkins 里面的 Xcode 插件配置里面把脚本拷贝出来,自己用命令行到项目目录下去执行,调试一下,这种情况我没遇到过,我觉得肯能是 cocoapod 所有者跟你执行命令不是用一个用户。

  • lieyunye

    我就是用jenkins做自动化打包上传到upyun提供下载,解脱了之前每次都得改改改改

  • hw

    我很鄙视一些博客的原因就是文章没有发表时间

    • answerhuang

      是么,那就麻烦看看 URL。

      • summer

        good idea

  • Pingback: iOS移动开发周报-第43期 | 微时代

  • Pingback: iOS移动开发周报-第43期

  • Pingback: iOS移动开发周报-第43期 – 剑客|关注科技互联网

  • Calvin

    如果邮件里需要加入更新说明呢?

    • answerhuang

      可以在项目里面维护一个更新日志的文件,打包的时候脚本去读这个文件。

  • Calvin

    看完之后, 我只想说我也要学会这个偷懒方法^_^

  • Pingback: WWDC 2015 将于 6 月 8 日在旧金山开幕 – iOS 移动开发周报 – 剑客|关注科技互联网