一、Homebrew
Homebrew
是一款Mac OS
平台下的软件包管理工具
- 安装Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- 检测Homebrew是否安装成功
brew -v
- 更新Homebrew
brew update
注意
1、Homebrew的命令是以brew开头
2、Homebrew的默认安装目录为 /usr/local/Homebrew
3、通过brew 安装的程序都会默认安装到 /usr/local/Cellar/程序名/版本号/ 目录下
二、Java
- Jenkins需要依赖java环境,当我们用最新的Homebrew来安装Jenkins时会默认先安装 java11,但是我们最好使用java8,Java8比较稳定,而且后面流水线要用bugly,bugly不支持Java11。
- brew安装Java8
brew install --cask homebrew/cask-versions/adoptopenjdk8
- 检测Java是否安装成功
java -version
注意
1、JAVA的默认安装目录为 /Library/Java,如果你安装多个版本,/Library/Java/JavaVirtualMachines里面就可以看到多个版本文件夹
二、Jenkins
Jenkins是开源软件项目,基于Java开发的持续集成工具,用于监控持续重复的工作
- brew安装Jenkins
brew install jenkins
- 检测Jenkins是否安装成功
jenkins --version
- 启动jenkins
jenkins
jenkins是在前台启动关闭终端,jenkins就关闭了
- 设置jenkins后台启动、开机启动
设置开机自启动:sudo launchctl load -w /Library/LaunchDaemons/org.jenkins-ci.plist
取消开机自启动:sudo launchctl unload -w /Library/LaunchDaemons/org.jenkins-ci.plist
后台启动(默认端口):nohup java -jar jenkins.war &
后台启动(指定端口):nohup java -jar jenkins.war -httpPort=88 &
后台启动(HTTPS):nohup java -jar jenkins.war -httpsPort=88 &
- 根据提示输入,安装推荐的插件,注册账户
- 你可以把所有的插件都安装了,常用的有git相关Branch API Plugin、 Build With Parameters之类
三、流水线
-
创建新的流水线任务,名字你自己取
-
配置Discard old builds选项,就是多久释放旧的构建
-
勾选This project is parameterized,选择Choice Parameter,这边的environment名字和内容,其实你都可以按需配置,只要和下面脚本里对的上就可以。这边就是选择对应的环境,开发、测试、生产
-
选择Git Parameter,就是可以选择对应的Git分支
-
Git源码管理,填入你的源码地址,我这边用的是https的,点这个添加,输入你的git账号和密码就可以了。
- 如果你是SSH,你就选择SSH Username with private key,把ssh私钥填进去
6.1 前往文件夹 ~/.ssh 可以看到本机是否已经生成过,有的话可以直接用,也可以生成新的
6.2 ssh-keygen -t rsa -C "[email protected]" 生成秘钥;不需要更名称和不需要密码的话直接敲回车就行了。
6.3 生成成功之后,前往 ~/.ssh,里面三个文件id_rsa(私钥)、id_rsa.pub(公钥)、known_hosts
6.4 将id_rsa.pub(公钥)配置到git,将id_rsa(私钥)配置到jenkins里。
- 构建->增加构建步骤->
Execute shell
- 在填脚本,我们先把钉钉弄一下
8.1 钉钉和测试拉个群
8.2 群设置->智能群助手->添加自定义机器人
8.3 安全设置,必须要选一个,我选择了关键词 比较简单一点,这个关键词就是你机器人自动发的文字里必须要有这个关键词才会发,例如发布
。复制Webhook
备用 - 查看蒲公英的
apikey
,在个人设置
里
- 因为xcodebuild打包需要
ExportOptions.plist
文件。所以前往文件夹~/.jenkins/workspace,在这个目录下创建文件夹ExportOptions。 - 先手动导出你的IPA包,类型的话你就选ad-hoc,导出的文件里有个ExportOptions.plist,把它copy出来,放到刚刚的文件夹里,再复制一份然后修改里面的method属性为
development
,把这个文件重命名为ExportOptions_dev.plist
。
- 因为我签名是自动的,所以我不需要配证书什么的,比较方便,直接用了jenkins的脚本,如果你是手动的。还是用
fastlane
比较方便 - 输入脚本,把脚本复制出来,你全局搜一下****,有****的地方就是你需要自己替换的
echo -e $(pwd)
## !/bin/sh
## 项目名
TARGET_NAME=****
## Scheme名
SCHEME=****
echo -e "============Pod Install============"
cd ${TARGET_NAME}
echo -e $(pwd)
pod install
##=======================
## 编译类型
if [[ "${environment}" == "生产环境" ]]; then
# 生产环境
BUILD_TYPE=Release
## ExportOptions.plist文件的存放路径,该文件要存放在这个路径下内容如下
EXPORTOPTIONSPLIST=${JENKINS_HOME}/workspace/ExportOptions/ExportOptions.plist
else
# 测试环境
BUILD_TYPE=Debug
## ExportOptions.plist文件的存放路径,该文件要存放在这个路径下内容如下
EXPORTOPTIONSPLIST=${JENKINS_HOME}/workspace/ExportOptions/ExportOptions_dev.plist
fi
## 当前目录
SORCEPATH=${WORKSPACE}
## workspace名
SPACE=${WORKSPACE}/${TARGET_NAME}/${TARGET_NAME}.xcworkspace
##xcarchive文件的存放路径
ARCHIVEPATH=$SORCEPATH/build/$SCHEME.xcarchive
## ipa文件的存放路径
EXPORTPATH=$SORCEPATH/build/$SCHEME
## 导出后的ipa路径
EXPORTPATHIPA=$SORCEPATH/build/${TARGET_NAME}/****.ipa
echo -e "============First Build Clean============"
## 清理缓存
## 如果工程使用的是cocoapods,则'-project %s.xcodeproj'替换为'-workspace %s.xcworkspace'
xcodebuild clean -workspace $SPACE -scheme ${SCHEME} -configuration ${BUILD_TYPE}
DELETEIPAFILE=$SORCEPATH/build/$SCHEME/****.ipa
rm -f ${DELETEIPAFILE}
echo -e "============Build Clean============"
## 输出关键信息
echo -e " TARGET_NAME : ${TARGET_NAME}"
echo -e " BUILD_TYPE : ${BUILD_TYPE}"
echo -e " SORCEPATH : ${SORCEPATH}"
echo -e " ARCHIVEPATH : ${ARCHIVEPATH}"
echo -e " EXPORTPATH : ${EXPORTPATH}"
echo -e " EXPORTOPTIONSPLIST : ${EXPORTOPTIONSPLIST}"
echo -e "============Build Archive============"
## 导出archive包
xcodebuild archive -workspace ${SPACE} -scheme ${SCHEME} -configuration ${BUILD_TYPE} -quiet -archivePath $ARCHIVEPATH
echo -e "============Build Archive Success============"
echo -e "============Export IPA============"
## 导出IPA包
xcodebuild -exportArchive -archivePath $ARCHIVEPATH -quiet -exportPath ${EXPORTPATH} -exportOptionsPlist ${EXPORTOPTIONSPLIST}
echo -e "============Export IPA SUCCESS============"
## 编译完成时间
BUILD_DATE="$(date +'%Y%m%d_%H%M')"
## 上传蒲公英
## apiKey和userKey需要在蒲公英的账号设置中查找https://www.pgyer.com/account/api
apiKey="****"
MSG=`git log -1 --pretty=%B`
#蒲公英打包
result=$(curl -F "file=@${EXPORTPATHIPA}" \
-F "_api_key=${apiKey}" \
-F "buildUpdateDescription=${environment};${MSG}" \
https://www.pgyer.com/apiv2/app/upload)
code=`echo $result | jq '.code'`
if [ $code = 0 ];then
echo "蒲公英打包 Success"
data=`echo $result | jq '.data'`
#APP名 需要带上-r 要不然数据会有""
buildName=`echo $data | jq -r '.buildName'`
#APP版本号
buildVersion=`echo $data | jq -r '.buildVersion'`
#APP下载二维码
buildQRCodeURL=`echo $data | jq -r '.buildQRCodeURL'`
#钉钉通知
message="#### 【iOS${buildName}】${environment};V${buildVersion} 发布成功 \n 更新说明:${MSG} \n>扫描二维码安装:![screenshot](${buildQRCodeURL}) \n #### @****钉钉群里你需要at的人的手机号码 请注意查收"
MSG_JSON='{"msgtype":"markdown","markdown":{"title":"'${buildName}'App发布通知","text":"'${message}'"},"at":{"atMobiles":["****钉钉群里你需要at的人的手机号码"]}}'
curl 'https://oapi.dingtalk.com/robot/send?access_token=****钉钉机器人webhook' \
-H 'Content-Type:application/json' \
-d "${MSG_JSON}"
else
echo "蒲公英打包 Failed"
fi
-
构建任务
-
如果你需要在
git push
的时候自动执行,那就设置构建触发器
,然后将这个GitLab webhook URL复制到你的项目设置里,一般叫网络回调钩子
。
四、分配角色权限
因为要给后端和测试同学使用,需要配置一下权限,给他们指定某些任务可以操作,具体的操作也只能是运行和取消。
- 安装插件
Role-based Authorization Strategy
-
Manage Jenkins->Manage Users->新增用户test
-
Manage Jenkins->Configure Global Security->勾选Role-Based Strategy ,保存(如果你没有安装Role-based Authorization Strategy插件是没有这个选项的)
- Manage Jenkins->Manage and Assign Roles 进入角色管理
4.1 选择Manage Roles
,这边我的理解是用户组的意思,你输入一个用户组的名字,选择读权限
4.2 输入4.1你输的用户组名
,然后在Pattern
输入对应的任务名字,进行绑定,选择对应的权限。相当于你这个组下的用户只能操作这个任务
4.3 选择Assign Roles
,给对应的用户组,分配用户
4.4 绑定用户组和用户,拉到最下面有个保存
-
登录test账号,发现只能看到那一个任务,也只有运行和停止的操作 就OK了
五、外网映射
- 因为测试同学不一定和咱们处于同一个区域网,咱们需要给个
外网地址
给他们,那我们需要用到一个工具花生壳
,自行搜索下载。花生壳默认是开机自启的,这个软件有时候后端在测支付的时候 也是可以用它的。 -
添加映射
-
输入你本机的IP地址(按住option,去点击你的WiFi图标,可以看到你的IP),端口是8080,保存
-
将生成的访问地址,发给测试他们试试吧
六、Fastlane的使用
fastlane可以简化我们的操作,之前的shell脚本那么长 很不方便。在集成fastlane之前,咱们先创建一个新的jenkins任务,里面把上面讲的git等相关的东西先弄好。
- 安装fastlane
brew install fastlane
- 查看fastlane版本
fastlane --version
- 进入你的
工程
目录下,初始化,选择4 然后下一步确认键就可以了
fastlane init
- 成功后会生成fastlane文件夹,里面有Appfile、Fastfile两个文件
- Appfile主要是填写你的app_identifier和apple_id账号的, Fastfile就是你的操作文件了,里面包含了多个lane ,每个lane你就可以想成是个任务或者方法。
- 进入你的
工程
目录下,添加蒲公英插件,然后会多Gemfile Gemfile.lock Pluginfile文件
fastlane add_plugin pgyer
- 填写Appfile账号信息
app_identifier "****"
apple_id "****"
- 编写fastlane任务,gym(clean:true,scheme:"XMHealth",configuration:"Release",export_method:"ad-hoc"),configuration有release和debug,export_method即导出参数有app-store, package, ad-hoc, enterprise, development, 和developer-iddevelopment。你搜一下里面有****的做一下替换。至于lane传参数,你可以看一下官网传参的介绍。
default_platform(:ios)
platform :ios do
desc "build adhoc ipa"
lane :XMHealth_adhoc do
gym(clean:true,scheme:"****",configuration:"Release",export_method:"ad-hoc")
end
desc "build dev ipa"
lane :XMHealth_dev do
gym(clean:true,scheme:"****",configuration:"Debug",export_method:"development")
end
desc "upload to pgyer"
lane :uploadToPgyer do |options|
pgyer(api_key: "****", user_key: "****", update_description: options[:msg])
end
desc "upload to dingdingTalk"
lane :dingdingTalk do |options|
updatemsg = options[:msg]
buildName = get_info_plist_value(path: "./XMHealth/Other/Info.plist", key: 'CFBundleDisplayName')
puts buildName
curl = %Q{
curl 'https://oapi.dingtalk.com/robot/send?access_token=****' \
-H 'Content-Type:application/json' \
-d '{
"msgtype":"markdown",
"markdown":{
"title":"iOS#{buildName}App发布通知",
"text":"#### iOS#{buildName}App发布成功\n说明:#{updatemsg}\n###### 扫码安装↓↓↓\n![screenshot](https://www.pgyer.com/app/qrcode/****)\n#### @**** @**** 请注意查收"
},
"at":{
"atMobiles":["****","****"]
}
}'
}
system curl
end
desc "release"
lane :release do |options|
if options[:submit]
XMHealth_adhoc()
uploadToPgyer(msg:options[:msg])
dingdingTalk(msg:options[:msg])
puts "生产ad-hoc流水线成功"
else
XMHealth_dev()
uploadToPgyer(msg:options[:msg])
dingdingTalk(msg:options[:msg])
puts "测试dev流水线成功"
end
end
end
- jenkins里execute shell
## 项目名
TARGET_NAME=****
GITMSG=`git log -1 --pretty=%B`
MSG="${environment}、${GITMSG}"
cd ${TARGET_NAME}
pod install
## 编译类型
if [[ "${environment}" == "生产环境" ]]; then
# 生产环境
fastlane release submit:true msg:${MSG}
else
# 测试环境
fastlane release submit:false msg:${MSG}
fi
- 专门搞一台闲置的Mac天天开着,在上面部署好,然后用花生壳,开放给测试、后台他们使用
常见问题
- 如果有Java相关的报错,记得检查你本地的环境变量还有安装的Java,JAVA的默认安装目录为 /Library/Java,看看里面是不是安装了多个,建议使用
java8
,jenkins默认是Java11
的,
1.1 检查. zshrc文件的里的环境变量JAVA_HOME,前往->文件夹-> ~/. zshrc
1.2 如果有缺JAVA_HOME,请添加你对应的Java地址
1.3 命令行里source .zshrc,保存一下
export JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/Contents/Home"
- 输出里看到如下错误
DVTPortal: Error:
Error Domain=DVTPortalServiceErrorDomain Code=1100 "Your session has expired. Please log in."
解决:
Xcode —>Preference—> Accounts
重新登录,注意如果有多个账号,要确保所有的账号都是登录状态。
- 在jenkins里执行xcodebuild -exportArchive 导出IPA命令的时候,会报错
error: exportArchive: The data couldn’t be read because it isn’t in the correct format.
Error Domain=NSCocoaErrorDomain Code=3840 "No value." UserInfo={NSDebugDescription=No value., NSFilePath=/var/folders/qx/qs4cc3pn0sgddxqjh7dj_k300000gn/T/ipatool-json-filepath-~~~FH2VEz}
** EXPORT FAILED **
Build step 'Execute shell' marked build as failure
Finished: FAILURE
解决:
将对应打包的证书ExportOptions.plist
文件的compileBitcode
内容由 true 改为 false 就可以
1、Could not find action, lane or variable 'pgyer'. Check out the documentation for more details: https://docs.fastlane.tools/actions
找不到蒲公英插件,原来是安装目录错了,应该在工程目录下安装:fastlane add_plugin pgyer