Jenkins下的Android与iOS打包

Jenkins下的Android与iOS打包

九月 16, 2020

引入Jenkins进行App打包的缘由

在完整的App开发流程中,在以往的流程体系中,测试工程师要想获得最新代码版本的App包,必须要找研发进行打包,随着敏捷开发在App测试流程中运用的越来越广泛,效率越来越被重视,因此为了提高效率,减少研发与测试间的沟通成本,引入了CI/CD持续集成进行打包,当然,到现在这已经是非常成熟的技术,在此记录一下真正投入的生成环境中的Jenkins App打包,包含Android和iOS两端。

App打包(Android)

首先来介绍一下Android端下的打包的大致流程,在Jenkins中进行配置,首先需要设置打包的版本号(VersionCode)以及版本名(VersionName)首先在General中的parameterized中增加String Parameter和Choice Parameter,增加的一些参数如下图所示:

Choice Parameter选项参数设置,BUILD_TYPE可与研发人员确认打包的分支中的字段,即可控制build出的是Debug的apk还是Release的apk包

版本号(VERSION_CODE)

版本名(VERSION_NAME)

Jenkins-CRUMB值

以及需要设置Git Parameter,设置此选项可以在打包的时候提供代码分支选择

这里的所填写的Name要与下方源码管理中的指定分支保持一致,的在Parameter Type那里选择Branch or Tag,这里设置的默认分支为origin/master,当然可以设置为你默认要选择的分支。

之后再Build Environment中可设置打包的Build-Name,每次进行Build构建时就可以显示每次打包对应的编号,方便出现问题时进行索引寻找。

在构建中加入shell命令来设置每次打包时的版本号,因为拉到Jenkins workspace中的代码文件夹目录因人而异,所以具体可以对应到自己Jenkins构建的文件夹,命令如下:

1
sed -i '' "s/JENKINS_BUILD_NUMBER.*/JENKINS_BUILD_NUMBER=\ \"-${BUILD_NUMBER}\"/g" /var/root/.jenkins/项目文件夹/gradle.properties

主要的作用就是在编译前替换编译项目中gradle.properties中的配置项。然后需要引入一下Jenkins安装的gradle,版本适用于脚本即可,Gradle在Jenkins设置中的Global Tool Configuration中安装即可。

构建后需要将打好的apk输出到本地并且支持在console output中打印下载链接,这里默认文件夹地址以Mac为例,若在本地文件夹中没有此版本名的文件夹时,会默认创建文件夹及该版本名文件夹下的debug文件夹和release文件夹,如下:

1
2
3
4
if [ ! -d "/Library/WebServer/Documents/workspaces/本地文件夹/${VERSION_NAME}" ];then
mkdir -p "/Library/WebServer/Documents/workspaces/本地文件夹/${VERSION_NAME}/debug"
mkdir -p "/Library/WebServer/Documents/workspaces/本地文件夹/${VERSION_NAME}/release"
fi

然后会分为两种情况,一个是build的是debug包,另外构建的是release包,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if [ ${BUILD_TYPE} != Debug ];then
cp /private/var/root/.jenkins/workspace/项目文件夹/app/build/outputs/apk/release/app-release.apk /Library/WebServer/Documents/workspaces/本地文件夹/${VERSION_NAME}/release/
echo "APKSize:"`ls -l /Library/WebServer/Documents/workspaces/本地文件夹/${VERSION_NAME}/release/app-release.apk | awk '{print $5}'`
mv /private/var/root/.jenkins/workspace/项目文件夹/app/build/outputs/apk/release/app-release.apk /private/var/root/.jenkins/workspace/项目文件夹/apk/release.apk2
mv /Library/WebServer/Documents/workspaces/本地文件夹/${VERSION_NAME}/release/app-release.apk /Library/WebServer/Documents/workspaces/本地文件夹/${VERSION_NAME}/release/${JOB_NAME}-${BUILD_NUMBER}-${BUILD_TYPE}-${VERSION_NAME}-${VERSION_CODE}-${SVN_VERSION}-${BUILD_TIMESTAMP}.apk
echo downloadAPK:http://你的本地ip地址/workspaces/本地文件夹/${VERSION_NAME}/release/${JOB_NAME}-${BUILD_NUMBER}-${BUILD_TYPE}-${VERSION_NAME}-${VERSION_CODE}-${SVN_VERSION}-${BUILD_TIMESTAMP}.apk
echo ${VERSION_NAME}/release/${JOB_NAME}-${BUILD_TYPE}-${VERSION_NAME}-${VERSION_CODE}-${SVN_VERSION}-${BUILD_TIMESTAMP}.apk > /Users/dev-debug/Desktop/Jenkins/apkdownloadurl.txt
else
cp /private/var/root/.jenkins/workspace/项目文件夹/app/build/outputs/apk/debug/app-debug.apk /Library/WebServer/Documents/workspaces/本地文件夹/${VERSION_NAME}/debug/
echo "APKSize:"`ls -l /Library/WebServer/Documents/workspaces/本地文件夹/${VERSION_NAME}/debug/app-debug.apk | awk '{print $5}'`
mv /private/var/root/.jenkins/workspace/项目文件夹/app/build/outputs/apk/debug/app-debug.apk /private/var/root/.jenkins/workspace/项目文件夹/apk/debug.apk2
mv /Library/WebServer/Documents/workspaces/本地文件夹/${VERSION_NAME}/debug/app-debug.apk /Library/WebServer/Documents/workspaces/本地文件夹/${VERSION_NAME}/debug/${JOB_NAME}-${BUILD_NUMBER}-${BUILD_TYPE}-${VERSION_NAME}-${VERSION_CODE}-${SVN_VERSION}-${BUILD_TIMESTAMP}.apk
echo downloadAPK:http://你的本地ip地址/workspaces/本地文件夹/${VERSION_NAME}/debug/${JOB_NAME}-${BUILD_NUMBER}-${BUILD_TYPE}-${VERSION_NAME}-${VERSION_CODE}-${SVN_VERSION}-${BUILD_TIMESTAMP}.apk
echo ${VERSION_NAME}/debug/${JOB_NAME}-${BUILD_TYPE}-${VERSION_NAME}-${VERSION_CODE}-${SVN_VERSION}-${BUILD_TIMESTAMP}.apk > /Users/dev-debug/Desktop/Jenkins/apkdownloadurl.txt
fi
exit 0

以上,Android打包操作就大体完成了。

app打包(iOS)

其实iOS端的打包过程与Android端的大体流程是一致的,只是在设置钥匙串的时候比较头疼一点,需要导入iPhone Developer的开发证书,在执行xcodebuild时需要先引入证书才可进行打包,之前关于String Parameter和Choice Parameter与Android的是大体一致的,这里就不再过多的赘述,下面为例:

版本号(VERSION_CODE)

版本名(VERSION_NAME)

Git Parameter,这里的设置和Android的可以理解为一致

这里需要注意的是,iOS打包时需要引入开发者证书的,这里Jenkins下的设置如下:

因为每次拉取的archive文件过大,导致占了很多的空间,所以在每次构建之前都加入命令对archive文件进行清理,如下:

1
2
3
4
5
6
7
if [ ! -d "/Library/WebServer/Documents/workspaces/项目文件夹/${VERSION_NAME}/${VERSION_CODE}" ];then
mkdir -p "/Library/WebServer/Documents/workspaces/项目文件夹/${VERSION_NAME}/${VERSION_CODE}"
fi
if [ -d "archive/${VERSION_NAME}/${VERSION_CODE}" ];then
touch archive/${VERSION_NAME}/${VERSION_CODE}/test.txt
rm -r archive/${VERSION_NAME}/${VERSION_CODE}/*
fi

之后对info.plist文件中的配置项进行一些替换

1
2
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $VERSION_CODE" "/Users/dev-debug/.jenkins/workspace/项目文件夹/info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $VERSION_NAME" "/Users/dev-debug/.jenkins/workspace/项目文件夹/info.plist"

然后执行xcodebuild操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
echo "start build VoiceChat"
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
export LC_ALL=en_US.UTF-8
security unlock-keychain -p “设置的root密码” ~/Library/Keychains/login.keychain

workspace_path=.
project_name=项目名

xcodebuild clean
xcodebuild archive -workspace $project_name.xcworkspace -scheme $project_name -configuration Debug -archivePath archive/${VERSION_NAME}/${VERSION_CODE}/$project_name-${BUILD_NUMBER}.xcarchive CODE_SIGN_IDENTITY="开发者证书名称" -quiet
xcodebuild -exportArchive -exportOptionsPlist archive/archiveOpt.plist -archivePath archive/${VERSION_NAME}/${VERSION_CODE}/$project_name-${BUILD_NUMBER}.xcarchive -exportPath ./export/ -configuration Debug -quiet
mv ./export/app.ipa /Library/WebServer/Documents/workspaces/本地文件夹/${VERSION_NAME}/${VERSION_CODE}/${JOB_NAME}-${BUILD_NUMBER}-${VERSION_NAME}-${VERSION_CODE}.ipa
echo DownloadIPA:http://你的ip地址/workspaces/本地文件夹/${VERSION_NAME}/${VERSION_CODE}/${JOB_NAME}-${BUILD_NUMBER}-${VERSION_NAME}-${VERSION_CODE}.ipa

最后,在执行完打包操作后,因项目接入了Firebase来监控app的质量,而iOS接入Firebase的话需要上传对应版本的dSYM文件,下面是上传dSYM命令:

1
/Users/dev-debug/.jenkins/workspace/项目文件夹/Pods/FirebaseCrashlytics/upload-symbols -gsp /Users/dev-debug/.jenkins/workspace/项目文件夹/GoogleService-Info.plist -p ios /Users/dev-debug/.jenkins/workspace/项目文件夹/archive/${VERSION_NAME}/${VERSION_CODE}/项目名-${BUILD_NUMBER}.xcarchive/dSYMs/SoulFa.app.dSYM

至此,整个iOS的打包过程就完成了,测试工程师可以在不影响研发工程师的情况下自行进行对应分支的代码进行打包了。

总结

在APP测试中,打包是一个很基础也是比较关键的一个过程,将打包过程接入Jenkins,对于打包效率起到了提升作用,也减少了研发与测试之间沟通成本,现在大部分的APP开发流程都引用了这种方式。

以上是对这次持续集成学习的记录。