给iOS工程增加Daily Build

前言

Daily Build 是一件非常有意义的事情,也是敏捷开发中关于 “持续集成” 的一个实践。Daily Build 对于开发来说有如下好处:

  • 保证了每次 check in 的代码可用,不会造成整个工程编译失败。
  • 进度跟进。产品经理可以每天看到最新的开发进度,并且试用产品,调整一些细节。很多时候,一个新功能,你真正用了一下才能有体会好或不好,所以 daily build 也给产品经理更多时间来调理他的设计。
  • 需求确认。产品经理可以确认开发的功能细节是他的预期。因为我们的开发比较紧凑,所以都没有传统的需求说明文档,所以 daily build 也给产品经理用于尽早确认开发的功能细节是他的预期,我就遇到一次产品经理发现开发出的一个功能细节和他的预期不一致,但是因为有 daily build,使得我可以尽早做修改,把修改的代价减小了。
  • 测试跟进。如果功能点是独立的话,测试同事完全可以根据 daily build 来进行一些早期的测试。越早的 Bug 反馈可以使得修改 bug 所需的时间越短。

步骤

xcodebuild 命令

如何做 daily build 呢?其实 Xcode 就提供了命令行 build 的命令,这个命令是 xcodebuild,用 xcodebuild -usage 可以查看到所有的可用参数,如下所示:

1
2
3
4
5
6
7
[tangqiao ~]$xcodebuild -usage
Usage: xcodebuild [-project <projectname>] [[-target <targetname>]...|-alltargets] [-configuration <configurationname>] [-arch <architecture>]... [-sdk [<sdkname>|<sdkpath>]] [<buildsetting>=<value>]... [<buildaction>]...
       xcodebuild [-project <projectname>] -scheme <schemeName> [-configuration <configurationname>] [-arch <architecture>]... [-sdk [<sdkname>|<sdkpath>]] [<buildsetting>=<value>]... [<buildaction>]...
       xcodebuild -workspace <workspacename> -scheme <schemeName> [-configuration <configurationname>] [-arch <architecture>]... [-sdk [<sdkname>|<sdkpath>]] [<buildsetting>=<value>]... [<buildaction>]...
       xcodebuild -version [-sdk [<sdkfullpath>|<sdkname>] [<infoitem>] ]
       xcodebuild -list [[-project <projectname>]|[-workspace <workspacename>]]
       xcodebuild -showsdks

一般情况下的命令使用如下:

1
xcodebuild -configuration Release -target "YourProduct"

但在 daily build 中,用 Release 用为 configuration 其实不是特别好。因为 Release 的证书可能会被经常修改。我们可以基于 Release 的 Configuation,建一个专门用于 daily build 的 configuration。方法是:在工程详细页面中,选择 Info 一栏,在 Configurations 一栏的下方点击 “+” 号,然后选择 “Duplicate Release Configuration”, 新建名为 “DailyBuild” 的 Configuration, 如下图所示:

之后就可以用如下命令来做 daily build 了

1
xcodebuild -configuration DailyBuild -target "YourProduct"

执行完命令后,会在当前工程下的 build/DailyBuild-iphoneos/ 目录下生成一个名为: YourProduct.app 的文件。这个就是我们 Build 成功之后的程序文件。

生成 ipa 文件

接下来我们需要生成 ipa 文件,在生成 ipa 文件这件事情上,xcode 似乎没有提供什么工具,不过这个没什么影响,因为 ipa 文件实际上就是一个 zip 文件,我们使用系统的 zip 命令来生成 ipa 文件即可。需要注意的是,ipa 文件并不是简单地将编辑好的 app 文件打成 zip 文件,它需要将 app 文件放在一个名为 Payload 的文件夹下,然后将整个 Payload 目录打包成为 .ipa 文件,命令如下:

1
2
3
4
5
cd $BUILD_PATH
mkdir -p ipa/Payload
cp -r ./DailyBuild-iphoneos/$PRODUCT_NAME ./ipa/Payload/
cd ipa
zip -r $FILE_NAME *

生成安装文件

苹果允许用 itms-services 协议来直接在 iphone/ipad 上安装应用程序,我们可以直接生成该协议需要的相关文件,这样产品经理和测试同学都可以直接在设备上安装新版的应用了。相关的参考资料可以见:这里 和 这里

具体来说,就是需要生成一个带 itms-services 协议的链接的 html 文件,以及一个 plist 文件。

生成 html 的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat << EOF > install.html
<!DOCTYPE HTML>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title> 安装此软件 </title>
  </head>
  <body>
    <ul>
      <li> 安装此软件:<a href="itms-services://?action=download-manifest&url=http%3A%2F%2Fwww.yourdomain.com%2Fynote.plist">$FILE_NAME</a></li>
    </ul>
    </div>
  </body>
</html>
EOF

生成 plist 文件的代码如下,注意,需要将下面的涉及 www.yourdomain.com 的地方换成你线上服务器的地址,将 ProductName 换成你的 app 安装后的名字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
cat << EOF > ynote.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
   <key>items</key>
   <array>
       <dict>
           <key>assets</key>
           <array>
               <dict>
                   <key>kind</key>
                   <string>software-package</string>
                   <key>url</key>
                   <string>http://www.yourdomain.com/$FILE_NAME</string>
               </dict>
               <dict>
                   <key>kind</key>
                   <string>display-image</string>
                   <key>needs-shine</key>
                   <true/>
                   <key>url</key>
                   <string>http://www.yourdomain.com/icon.png</string>
               </dict>
           <dict>
                   <key>kind</key>
                   <string>full-size-image</string>
                   <key>needs-shine</key>
                   <true/>
                   <key>url</key>
                   <string>http://www.yourdomain.com/icon.png</string>
               </dict>
           </array><key>metadata</key>
           <dict>
               <key>bundle-identifier</key>
               <string>com.yourdomain.productname</string>
               <key>bundle-version</key>
               <string>1.0.0</string>
               <key>kind</key>
               <string>software</string>
               <key>subtitle</key>
               <string>ProductName</string>
               <key>title</key>
               <string>ProductName</string>
           </dict>
       </dict>
   </array>
</dict>
</plist>


EOF

定时运行

这一点非常简单,使用 crontab -e 命令即可。大家可以随意 google 一下 crontab 命令,可以找到很多相关文档。假如我们要每周 1-5 的早上 9 点钟执行 daily build,则 crontab 的配置如下:

1
0 9 * * * 1-5 /Users/tangqiao/dailybuild.sh >> /Users/tangqiao/dailybuild.log 2>&1

失败报警

在 daily build 脚本运行失败时,最好能发报警邮件或者短信,以便能够尽早发现。发邮件可以用 python 的 smtplib 来写,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import smtplib

sender = 'sender@devtang.com'
receivers = ['receiver@devtang.com']

message = """From: Alert <sender@devtang.com>
To: Some one <receiver@devtang.com>
Subject: SMTP email sample

Hope you can get it.
"""

try:
    obj = smtplib.SMTP('server.mail.devtang.com')
    obj.sendmail(sender, receivers, message)
    print 'OK: send mail succeed'
except Exception:
    print 'Error: unable to send mail'

上传

daily build 编译出来如果需要单独上传到另外一台 web 机器上,可以用 ftp 或者 scp 协议。如果 web 机器悲剧的是 windows 机器的话,可以在 windows 机器上开一个共享,然后用 mount -t smbfs 来将这个共享 mount 到本地,相关的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mkdir upload
mount -t smbfs //$SMB_USERNAME:$SMB_PASSWORD@$SMB_TARGET ./upload
if [ "$?" -ne 0 ]; then
    echo "Failed to mount smb directory"
    exit 1
fi
mkdir ./upload/$FOLDER
cp $FILE_NAME ./upload/$FOLDER/
if [ "$?" -eq 0 ]; then
    echo "[OK] $FILE_NAME is uploaded to $SMB_TARGET"
else
    echo "[ERROR] $FILE_NAME is FAILED to  uploaded to $SMB_TARGET"
fi
umount ./upload

遇到的问题

本来我写的自动化脚本在 Mac OS X 10.6 下运行得很好。但是升级到 lion 后,脚本在手动执行时很正常,但是在用 crontab 启动时就会出现找不到开发者证书的错误。在网上搜了很久也没有找到解决办法。最后我试了一下在 “钥匙串访问” 中把开发者证书从 “登录” 那栏拖动到 “系统” 那栏,居然就解决了,如下图所示:

另外我搜到 2 个类似的问题的解决方案,虽然对我这个没起作用,也一并放在这儿,或许对遇到类似问题的人有帮助:

总结

将以上各点结合起来,就可以用 bash 写出一个 daily build 脚本了。每天这一切都会自动完成,心情相当好。

转载地址:http://blog.devtang.com/blog/2012/02/16/apply-daily-build-in-ios-project/


另外一种方式(手动打包上传到服务器供下载):

iOS 7.1正式版发布了,之前使用itms-services://URL方式在线安装ipa文件的方法却失效了,点击的时候报错为:“无法安装应用程序,因xxx.com的证书无效”(错误界面见下图),这应该怎么解决呢?

其实iOS 7.1修改了manifest.plist文件的访问协议,之前可以通过http协议访问,在iOS 7.1之后必须使用https协议方式访问。


比如之前的链接代码为:

itms-services://?action=download-manifest&url=http://example.com/manifest.plist

在iOS 7.1之后,就需要修改为:

itms-services://?action=download-manifest&url=https://example.com/manifest.plist

需要一个SSL证书才能够实现在线安装ipa文件的功能。



下面是把app放到web site,让其他人通过Over the Air (OTA)下载安装的步骤。


前提: 能安装app的device需要被包含在你的provisioning profile里

ref link: https://help.apple.com/iosdeployment-apps/?lang=en-us#app43ad871e


Step 1 在你的project里,选择"iOS Device" in the active scheme (如果选择的是iPad simulator or iPhone simulator,那么menu "Product > Archive"是灰化的


Step 2 select menu "Product > Archive"来为你的project创建一个archive (it is recommended that build your project again before this action)

Step 3 这时应该会自动弹出organizer window (之后你可以通过menu "Window > Organizer"来打开它),并显示你刚创建的archive item in the archive list。Highlight the archive item, and then click "Distribute..." button

Step 4 select option "Save for enterprise or Ad-Hoc deployment", click "Next"

Step 5 set "Code Signing Identity" as default value, my default value is "Tomson Xu" (这应该是你在apple developer site创建的certificate name), click "Next"

Step 6 设置"Save as"为你的project name,设置存放生成文件的位置"Where",勾上"Save for Enterprise Distribution"。

Step 7 设置"Application URL"为即将生成的ipa将放到web site里的URL(e.g.http://xxx.xxx.xxx.xxx/CityUCAP.ipa),设置"Title"为任意text(注意它并不是安装后的app display name), click "Save" button. 这时它将创建一个ipa file和一个与ipa file同名的plist file (假设为 CityUCAP.ipa and CityUCAP.plist)

Step 8 把step 7生成的ipa and plist file复制到你的web site里 (注意:其url要和step 7设置的”Application URL“一样),然后创建一个html file as follow.

[html]  view plain copy
  1. <a href="itms-services://?action=download-manifest&url=http://xxx.xxx.xxx.xxx/
CityUCAP.plist">Install App</a>  

Step 9 你 需要添加2个MIME类型到你的web server ,否则安装过程中就有可能出错。下面以IIS为例添加MIME type

1. 打开IIS Manager,左边panel选定root node,然后在右边的panel double click "MIME Types"

2. right click 任意位置, select "Add...",分别添加下列2个MIME Type

File name extension: .ipa 

MIME Type: application/octet-stream


File name extension: .plist 

MIME Type: text/xml


3. restart your web server


Step 10. 在你的iPhone web browser里访问Step 8创建的html file,然后click link to install app!


转载地址:http://blog.csdn.net/remote_roamer/article/details/22754609

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值