最近为公司项目集成了Jenkins+fastlane,实现了持续集成,本文做一个记录,其中遇到了不少问题,文章末尾都会列出,后续也会补充. 以此记录.
简单介绍:
fastlane是用Ruby语言编写的一套自动化工具,它把不同的action结合在一起,比如证书管理,编译打包等.从而形成一个完整的自动化流程. 另外Jenkins是一个开源的自动化服务器,给我们提供了一个自动化的平台,通过Jenkins远程拉取代码,并配置一些信息,实现自动化分发,通知等功能.
fastlane安装与配置
如果没有安装Xcode命令行工具的话,
xcode-select --install
确保gem sources是https://gems.ruby-china.com/
localhost:Jenkins snailsleep$ gem sources
*** CURRENT SOURCES ***
https://gems.ruby-china.com/
如果不是的话请更改:
gem sources --remove 当前的source
gem sources -a https://gems.ruby-china.com
fastlane安装:
brew cask install fastlane
安装完后查看版本
localhost:Jenkins snailsleep$ fastlane --version
fastlane installation at path:
/Library/Ruby/Gems/2.6.0/gems/fastlane-2.144.0/bin/fastlane
-----------------------------
[✔] 🚀
fastlane 2.144.0
接下来要cd到我们的项目目录,然后执行
fastlane init
此时会询问我们用fastlane来做什么,这里可以选4
app_identifier("***","***","***") # The bundle identifier of your app
apple_id("***") # Your Apple email address
team_id "***" # Developer Portal Team ID
# For more information about the Appfile, see:
# https://docs.fastlane.tools/advanced/#appfile
主要的打包脚本配置都在Fastfile文件里编写,不同的lane就是不同的任务,我们可以新建一个lane,来做我们的打包任务(涉及隐私的内容用***代替)
lane :qwer do
ENV["FASTLANE_USER"] = "***"
ENV["FASTLANE_PASSWORD"] = "***"
cert(
development: true,
)
sigh(
app_identifier: "com.***.***",
readonly: false,
cert_id: "***",
development: true,
)
sigh(
app_identifier: "com.***.appwatchkitapp",
readonly: false,
cert_id: "***",
development: true,
)
sigh(
app_identifier: "com.***.appwatchkitapp.watchkitextension",
readonly: false,
cert_id: "***",
development: true,
)
build_app(
scheme: "***",
export_method: "development",
output_directory: "/Users/Shared/Jenkins/Home/workspace/IPAName",
output_name: "IPAName",
include_bitcode: false,
configuration: "Debug",
export_xcargs: "-allowProvisioningUpdates",
destination: "generic/platform=iOS"
)
#可以使用蒲公英插件上传并制作二维码,具体可见 https://www.pgyer.com/doc/view/fastlane
#pgyer(api_key: "***", user_key: "***")
end
因为我们项目中还包含watch,存在三个app_identifier,所以进行了三次sigh.获取certid方法已在文章末贴出.
因为我们给这个lane命名为qwer,所以在项目目录中执行fastlane qwer即可开始打包
如果显示这样就说明你打包成功了
Jenkins安装与配置
在 Jenkins的官网 下载最新的 war 包, 我这里选择的是LTS的Mac OS X的版本, 下载完成后会有个jenkins-2.204.2.pkg的包,双击进行安装即可
安装成功后,我们会在Applications目录里发现有Jenkins文件夹,里面有个jenkins.war文件, 我们进入到这个文件目录内来启动Jenkins
$ cd /Applications/Jenkins
$ java -jar jenkins.war --httpPort=8080
Jenkins启动成功后,我们就可以去浏览器访问
http://localhost:8080
我们会看到这个界面
需要输入密码,密码已经写入到了日志中,日志获取路径是
Linux
By default logs should be made available in /var/log/jenkins/jenkins.log, unless customized in /etc/default/jenkins (for *.deb) or via /etc/sysconfig/jenkins (for */rpm)
Windows
By default logs should be at %JENKINS_HOME%/jenkins.out and %JENKINS_HOME%/jenkins.err, unless customized in %JENKINS_HOME%/jenkins.xml
Mac OS X
Log files should be at /var/log/jenkins/jenkins.log, unless customized in org.jenkins-ci.plist.
按照文档中所述,我们去/var/log/jenkins 找到jenkins.log文件,打开它后可以看到
首次进入Jenkins配置首页后,会询问你自定义插件还是直接用推荐的,这里直接选的一键集成推荐插件
经过了几次重试,终于成功,会到下面这个界面
最终Jenkins安装完成!
这里我选择的是SSH Username with private key 然后把私钥填写好(~/.ssh/id_rsa这里复制私钥内容),当然前提是得在代码托管平台配置好SSH,我这是在Gitee已经配置好了.
在"构建"栏目里,通过"增加构建步骤--Execute shell" 可以添加一些脚本,如下图
我们还可以通过蒲公英Jenkins插件来上传包并生成二维码,并且通过以下脚本,用企业微信机器人,来通知群里每个人
curl '这里是企业微信群机器人的Webhook地址'
-H 'Content-Type: application/json' \
-d '
{
"msgtype": "news",
"news": {
"articles" : [
{
"title" : "iOS 测试包",
"description" : "修复***问题\n修复***问题",
"url" : "***",
"picurl" : "***",
}
]
}
}'
✨ 可能遇到的问题与解决办法
1. 执行完fastlane init后,在bundle update卡住了
如果按照文章开头的方式已经更换了gem source,但是依然卡住,可以进到项目目录找到Gemfile文件,打开后发现是这样的
source "https://rubygems.org"
gem "fastlane"
在这里我们再改一次source
source "https://gems.ruby-china.com"
gem "fastlane"
然后在当前目录下执行bundle update就可以啦
2. 出现 fastlane: command not found 怎么办?
这个情况一般是由于 jenkins 没有设置正确的 $PATH 环境变量导致的。正确设置的方法为:
在命令行下执行 echo $PATH,记录下输出的结果, 在 jenkins 中系统管理-系统设置中,找到 环境变量(Environment variables) 在 key 中填写 PATH,在 value 中填写第一步中输出的结果 保存即可。
3. fastfile里明明配置好了pp文件,可是总说找不到pp文件?
例如:
Exit status: 70
[11:24:53]: No provisioning profile provided
[11:24:53]: Make sure to pass a valid provisioning for each required target
[11:24:53]: Check out the docs on how to fix this: https://docs.fastlane.tools/actions/gym/#export-options
build_app里加上export_xcargs: "-allowProvisioningUpdates" (见文章中fastfile的lane部分)
4.certid怎么获取?
require 'spaceship'
Spaceship.login('***')
Spaceship.select_team
Spaceship.certificate.all.each do |cert|
cert_type = Spaceship::Portal::Certificate::CERTIFICATE_TYPE_IDS[cert.type_display_id].to_s.split("::")[-1]
puts "Cert id: #{cert.id}, name: #{cert.name}, expires: #{cert.expires.strftime("%Y-%m-%d")}, type: #{cert_type}"
end
以上脚本内容存好放在桌面,比如getcertID.rb,记得在Spaceship.login里改一下自己的开发者账号, 然后在命令行cd到桌面,执行
ruby getcertID.rb
输入开发者密码,即可获取所有certid
5. 启动Jenkins时候报错,端口号被占用
(base) localhost:Jenkins snailsleep$ java -jar jenkins.war --httpPort=8080
Running from: /Applications/Jenkins/jenkins.war
webroot: $user.home/.jenkins
2020-04-02 07:49:53.939+0000 [id=1] INFO org.eclipse.jetty.util.log.Log#initialized: Logging initialized @328ms to org.eclipse.jetty.util.log.JavaUtilLog
2020-04-02 07:49:54.051+0000 [id=1] INFO winstone.Logger#logInternal: Beginning extraction from war file
2020-04-02 07:49:55.387+0000 [id=1] WARNING o.e.j.s.handler.ContextHandler#setContextPath: Empty contextPath
2020-04-02 07:49:55.442+0000 [id=1] INFO org.eclipse.jetty.server.Server#doStart: jetty-9.4.z-SNAPSHOT; built: 2019-05-02T00:04:53.875Z; git: e1bc35120a6617ee3df052294e433f3a25ce7097; jvm 1.8.0_242-b08
2020-04-02 07:49:55.714+0000 [id=1] INFO o.e.j.w.StandardDescriptorProcessor#visitServlet: NO JSP Support for /, did not find org.eclipse.jetty.jsp.JettyJspServlet
2020-04-02 07:49:55.766+0000 [id=1] INFO o.e.j.s.s.DefaultSessionIdManager#doStart: DefaultSessionIdManager workerName=node0
2020-04-02 07:49:55.767+0000 [id=1] INFO o.e.j.s.s.DefaultSessionIdManager#doStart: No SessionScavenger set, using defaults
2020-04-02 07:49:55.769+0000 [id=1] INFO o.e.j.server.session.HouseKeeper#startScavenging: node0 Scavenging every 660000ms
2020-04-02 07:49:56.112+0000 [id=1] INFO hudson.WebAppMain#contextInitialized: Jenkins home directory: /Users/snailsleep/.jenkins found at: $user.home/.jenkins
2020-04-02 07:49:57.139+0000 [id=1] INFO o.e.j.s.handler.ContextHandler#doStart: Started w.@782a4fff{Jenkins v2.204.5,/,file:///Users/snailsleep/.jenkins/war/,AVAILABLE}{/Users/snailsleep/.jenkins/war}
2020-04-02 07:49:57.154+0000 [id=1] INFO o.e.j.server.AbstractConnector#doStop: Stopped ServerConnector@723ca036{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2020-04-02 07:49:57.155+0000 [id=1] INFO o.e.j.server.session.HouseKeeper#stopScavenging: node0 Stopped scavenging
2020-04-02 07:49:57.157+0000 [id=1] INFO hudson.WebAppMain#contextDestroyed: Shutting down a Jenkins instance that was still starting up
java.lang.Throwable: reason
at hudson.WebAppMain.contextDestroyed(WebAppMain.java:388)
端口号被占用,换个端口号即可:
$ cd /Applications/Jenkins
$ java -jar jenkins.war --httpPort=8080
6. 启动Jenkins时候报错,java版本不对
2020-02-27 16:50:30.475 defaults[94179:3383577]
The domain/default pair of (/Library/Preferences/org.jenkins-ci, httpsKeyStore) does not exist
2020-02-27 16:50:30.486 defaults[94180:3383580]
The domain/default pair of (/Library/Preferences/org.jenkins-ci, httpsKeyStorePassword) does not exist
JENKINS_HOME=/Users/Shared/Jenkins/Home
Jenkins command line for execution:
/usr/bin/java -Dfile.encoding=UTF-8 -XX:PermSize=256m -XX:MaxPermSize=512m -Xms256m -Xmx512m -Djava.io.tmpdir=/Users/Shared/Jenkins/tmp -jar /Applications/Jenkins/jenkins.war --httpPort=8080
OpenJDK 64-Bit Server VM warning: Ignoring option PermSize; support was removed in 8.0
OpenJDK 64-Bit Server VM warning: Ignoring option MaxPermSize; support was removed in 8.0
2月 27, 2020 4:50:30 下午 Main verifyJavaVersion
严重: Running with Java class version 57 which is not in the list of supported versions: [52, 55]. Run with the --enable-future-java flag to enable such behavior. See https://jenkins.io/redirect/java-support/
java.lang.UnsupportedClassVersionError: 57.0
at Main.verifyJavaVersion(Main.java:174)
at Main.main(Main.java:142)
Jenkins requires Java versions [8, 11] but you are running with Java 13 from /Library/Java/JavaVirtualMachines/openjdk-13.0.2.jdk/Contents/Home
java.lang.UnsupportedClassVersionError: 57.0
at Main.verifyJavaVersion(Main.java:174)
at Main.main(Main.java:142)
2020-02-27 16:50:40.839 defaults[94183:3383671]
注意 "Jenkins requires Java versions [8, 11] but you are running with Java 13" , Jenkins要求Java版本是8~11,我们需要去这个路径/Library/Java/JavaVirtualMachines/openjdk-13.0.2.jdk/Contents/Home,把openjdk-13.0.2.jdk删掉,然后我们再安装个Java8即可
安装Java8
$ brew tap AdoptOpenJDK/openjdk
$ brew cask install adoptopenjdk8
OK!搞定! 我们再次启动Jenkins,就会发现Jenkins is fully up and running ~
7. Jenkins跑项目的时候报错,need password
(见文章中fastfile文件的lane里) 打包脚本里需要添加以下内容,即为你的开发者账号和密码
ENV["FASTLANE_USER"] = "***"
ENV["FASTLANE_PASSWORD"] = "***"