iOS-持续集成

持续集成,就是一个自动化的操作,把一系列的操作通过脚本和工具串起来

梳理流程

这一步很重要,也是脚本开发的第一步。

1
2
3
4
5
6
7
8
9
10
11
graph TD
A[源码管理] --> B[依赖引入]
B --> C[环境配置]
C --> D[渠道选择]
D --> E[蒲公英/Fir.im]
D --> F[TestFlight]
E --> G[打包]
F --> L[打包]
G --> H[检测包]
H --> I[提取App信息]
I --> K[钉钉通知]

工具选择

功能 工具
整合功能 Jenkins
源码管理 Git
依赖引入 Cocoapods
环境配置 File
打包 fastlane
包检测 脚本
提取App信息 脚本
钉钉通知 脚本

Jenkins

工程根路径
Jenkins是开源CI/CD相对比较好的软件,提供超过1000个插件来支持构建、部署、自动化,满足任何项目的需要。

安装

一般运维会装,自己装的话自行百度,很简单。我先去装一个
咱不是专业的运维,只能按照教程装,配置好了,后期想卸载都不知道安装到哪了,所以我用的宝塔面板做控制。

配置

由于iOS打包只能在Mac上面运行,所以Jenkins要配置一个Mac的节点来处理

增加Mac机器节点



指定节点运行

脚本开发

依赖处理

1
2
3
4
5
6
7
export LANG=en_US.UTF-8
cd 工程根路径

pod repo update
cp ~/Desktop/libwebp.podspec.json ~/.cocoapods/repos/master/Specs/1/9/2/libwebp/1.1.0/libwebp.podspec.json

pod install

打包

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
echo "授权钥匙串访问权限"
security unlock-keychain -p 电脑密码 $HOME/Library/Keychains/login.keychain

firPublish() {
fir publish ipa包路径 --token=$1 --specify-icon-file=fastlane/logo.jpg --changelog=$ReleaseNotes
}


if [ "$ShowPlatform" == "$offical" ];then
echo $offical;
fastlane archive;
echo "打包结束"
checkIpa;
firPublish 8a073c443b2310a335a06223b2244a07;
elif [ "$ShowPlatform" == "$standby" ];then
echo $standby;
fastlane archive;
echo "打包结束"
checkIpa;
firPublish 909f3f4743198a622a0540c0685beab7;
elif [ "$ShowPlatform" == "$testflight" ];then
echo $testflight;
fastlane beta;
echo "打包结束"
fi

包检测

思想:检查ipa包创建时间是否离谱

1
2
3
4
5
6
7
8
9
10
11
12
13
fileName="xxx.ipa"
filePath="app/$fileName"
fileCreateTimeInterval=`date -r "$filePath" +%s`
nowTimeInterval=`date +%s`
diff=$(($fileCreateTimeInterval-$nowTimeInterval))
if [ 0 -gt $diff ];then
let diff=0-$diff
fi
limitTimeInterval=1800
if [ $diff -gt $limitTimeInterval ];then
echo "安装包检测有问题";
exit 2005
fi

提取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
export LANG=en_US.UTF-8
cd 工程根路径

appName=""
appVersion=""
appBuild=""
appBundleId=""
platform="iOS"

getAppInfo(){
basePath=`pwd`
ipaFilePath="$basePath/ipa包路径"
if [ ! -f "$ipaFilePath" ]; then
echo "未找到ipa包 $ipaFilePath"
exit 2002
fi

temIpaDirName="TempPayload"
temIpaDirPath="${basePath}/${temIpaDirName}"

if [ -d "$temIpaDirPath" ]; then
rm -rf "${temIpaDirPath}"
fi

if [[ -f "$ipaFilePath" ]]; then
unzip "$ipaFilePath" -d "$temIpaDirPath"
fi

appDir="$temIpaDirPath/Payload/`ls "$temIpaDirPath/"Payload`"
lcmInfoPlist="${appDir}/Info.plist"

appName=`/usr/libexec/PlistBuddy -c "Print :CFBundleName" $lcmInfoPlist`
appVersion=`/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" $lcmInfoPlist`
appBuild=`/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" $lcmInfoPlist`
appBundleId=`/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" $lcmInfoPlist`

if [ -d "$temIpaDirPath" ]; then
rm -rf "${temIpaDirPath}"
fi
}

getAppInfo

钉钉通知

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

offical="Fir.im-Official"
standby="Fir.im-Standby"
testflight="TestFlight"

if [ "$ShowPlatform" == "$testflight" ];then
exit 2001
fi

#钉钉通知
accessToken="55d47b6501debe7f10afe03805aa4453cc0299a70216124e615c8efecfae776a"
iconUrl="https://cdn.rencheng.cc/blog/zer9s.jpg-thumb100"
downloadUrl="http://fir.renchengqi.com/moegoios"

if [ "$ShowPlatform" == "$offical" ];then
downloadUrl="http://fir.mocaapp.cn/moego"
accessToken="0857ef061944b6796861a2a34e75bcfc27db2245037cf5e72b597c59e50d6e2b"
fi

url="https://oapi.dingtalk.com/robot/send?access_token=$accessToken"
header="Content-Type: application/json"

title="$appName($platform)更新"
text="[$appName($platform)更新]($downloadUrl)\n\n \
![$appName]($iconUrl)\n\n \
链接:[$downloadUrl]($downloadUrl)\n\n \
版本: $appVersion (Build: $appBuild)\n\n \
更新内容: $ReleaseNotes\n"

rawData="{ \"msgtype\":\"actionCard\", \
\"actionCard\": { \
\"title\": \"$title\", \
\"text\": \"$text\", \
\"hideAvatar\": \"0\", \
\"btnOrientation\": \"0\", \
\"singleTitle\": \"\" \
} \
}"

curl --request POST "$url" -H "$header" --data-raw "$rawData"