Jenkins Gitlab iOS 持续集成打包平台搭建
> 相关概念(markdown语法在我的电脑上写完发布不起作用不知道为啥后续排版内容容我看下纠正下)
Jenkins
jenkins 是java编写的开源的持续集成的工具,提供软件的开的持续集成服务,可以监控并触发持续重复的工作,支持多平台和插件拓展。(https://en.wikipedia.org/wiki/Jenkins_(software)
持续集成
持续集成 CI(continuous integration)
CI 敏捷开发的重要步骤,主要目的在于产品的快速迭代的同时保持高质量。
持续集成(CI)是一种实践,可以让团队在持续的基础上收到反馈并进行改进,不必等到开发周期后期才寻找和修复缺陷。
常见集成工具
Hudson
CruiseControl
Continuum
QuickBuild
Bamboo
Jenkins
TeamCity
CI-Eye
#《八大持续集成工具》http://openskill.cn/article/218
#持续集成(CI)、自动化构建和自动化测试–初探http://www.cnblogs.com/chaoa/articles/4447354.html
流程结构
平台搭建
需要的工具:Homebrew、java sdk、Jenkins
安装
Homenbrew已经java sdk的安装在此不做赘述直接进行Jenkins安装
安装:$ brew install jenkins
卸载:$ brew uninstall jenkins
启动: $ jenkins
登录
首次使用设置
该处的password根据提示可以找到->>>>/Users/bojoy-sdk1/.jenkins/secrets/initialAdminPassword
插件安装
创建AdminUser
根据提示填写相关信息进行创建
插件管理
常用的jenkins插件
git相关插件:Git client plugin 、Git plugin、Git server Plugin
GitHub相关插件:GitHub API Plugin、GitHub Branch Source Plugin、GitHub Organization Folder Plugin、GitHub plugin
gitLab相关插件:GitLab Authentication plugin、Gitlab Hook Plugin、GitLab logo Plugin、GitLab Plugin
xcode相关插件:Xcode integration(这里直接用sh命令进行编译)
插件安装
jenkins首页—>系统管理—>管理插件—>可选插件—>过滤搜索—>直接安装
配置工程文件
新建工程:Jenkins->新建->输入工程标题->工程类型选择为‘构建一个自由风格的软件项目’→ok
基础配置工程:
目标1:实现对gitlab的代码进行clone
实现该目标需要对工程的gitlab地址进行配置
设置好自后保存运行,进入~/.jenkins/workspace/工程名 可以发现你所添加的gitlab分支已经被clone到本地。
目标2:实现对clone的代码进行构建
实现该目标需要在目标1的基础上进行,在目标1中我们已经将需要的gitlab分支clone到本地,所以需要做的是对代码进行编译。生成ipa包。
在jenkins中可以使用shell命令xcodebuild
在‘构建’->'增加构建步骤'->' execute shell '->'Command'添加打包命令
因为需要调用‘Build/Products/’中.app 文件
所以需要将Build路径改变为包含在workspace中
在钥匙串中设置需要的证书权限
对shell命令进行编写
export LC_ALL="en_US.UTF-8"
echo "开始"
mkdir ~/Desktop/target
mkdir ~/Desktop/target/ios
APP=`pwd`/test/Build/Products/Release-iphoneos/test.app
DSYM=`pwd`/test/Build/Products/Release-iphoneos/test.app.dSYM
WS=`pwd`/test/test.xcworkspace
TS=`date +%Y%m%d_%H%M%S`
VER=`git rev-list head | sort | wc -l | awk '{print $1}'`
VER=`expr 2000000 + $VER`
IPA=~/Desktop/target/ios/$VER.ipa
if [ -d $APP ]; then
echo "delete $APP"
rm -r -f $APP
fi
if [ -d $DSYM ]; then
echo "delete $DSYM"
rm -r -f $DSYM
fi
if [ -d $IPA ]; then
echo "delete $IPA"
rm -r -f $IPA
fi
echo "编译"
xcodebuild -workspace $WS -scheme test \
-configuration Release \
-sdk iphoneos CODE_SIGN_IDENTITY="iPhone Distribution: junyan fan (JAYU2CSS9X)"
if [ ! -d $APP ]; then
echo "$APP build failed. Exit..."
exit
fi
xcrun -sdk iphoneos PackageApplication -v $APP -o $IPA
echo All Done!!!
保存设置构建工程。
目标3:实现在代码push之后自动对代码进行构建
使用gitlab中的web hooks 自动触发jenkins的构建
’构建触发器‘->'Build when a change is pushed to GitLab. GitLab CI Service URL:http://127.0.0.1:8080/project/test'
’高级‘->'Secret token'->'Generate'生成token
打开gitlab工程
填入对应的URL和Secret Token→'ADD Webhook'
点击‘test’如果出现
说明成功通过push自动构建。
目标4:实现对gitlab工程不同分支代码进行构建
这里需要引用到jenkins的‘参数化构建过程’配合‘Git Parameter Plug-In’插件使用
在目标3的基础上‘General’->'参数化构建过程'->'添加参数'→'Git Parameter'
这里是使用了GitParameter Plug-In插件,这里需要注意到的是Name一定要记下来在下面配置'源码管理'->'Git'->'Branches to build' 引用到
这两步设置之后进行构建,在构建是可以看到出现了branch这个选项
选择相应的branch就可以对需要的branch进行构建了。
目标5:实现对特定分支push后自动构建
因为是通过分支push所有jenkins构建的过程中全部都是按照默认的选择进行构建
所以在’Git Parameter‘->‘高级’→'Default value'中添加默认构建的分支参数
为了实现在push特定分支的情况下进行构建
所以在触发‘构建触发器‘添加push分支触发的参数
保存配置。到此为止目标5就已经实现了。
===========================是是是我就是分割线======================================
该文档只是jenkins众多功能中的一小部分,在最近这段时间的接触当中渐渐体会到了jenkins的强大之处,上
述的内容中工程配置所涉及的每一个点都还可以进行拓展,内容很多。包括打包之后的分发,自动测试等
该文档都没有涉及,但是jenkins是可以实现的。感兴趣的小伙伴可以在深入研究。
====================================自动测试======================================
上面我们提到了基本的jenkins自动构建编译,现在我们紧接上文看一看自动测试的相关内容
自动测试和自动编译打包的区别仅在于shell脚本的不同
echo "开始"
rmdir ~/Desktop/target
mkdir ~/Desktop/target
APP=`pwd`/Build/Products/Release-iphoneos/GFAutoTestDemo_XinMa.app
DSYM=`pwd`/Build/Products/Release-iphoneos/GFAutoTestDemo_XinMa.app.dSYM
WS=`pwd`/GFAutoTestDemo_XinMa.xcworkspace
TS=`date +%Y%m%d_%H%M%S`
VER=`git rev-list head | sort | wc -l | awk '{print $1}'`
VER=`expr 2000000 + $VER`
IPA=~/Desktop/target/$VER.ipa
echo $WS
if [ -d $APP ]; then
echo "delete $APP"
rm -r -f $APP
fi
if [ -d $DSYM ]; then
echo "delete $DSYM"
rm -r -f $DSYM
fi
if [ -d $IPA ]; then
echo "delete $IPA"
rm -r -f $IPA
fi
echo 导入插件
# pod update --no-repo-update
xcodebuild test -workspace $WS -scheme GFAutoTestDemo_XinMa -sdk iphonesimulator10.0 -destination 'platform=iOS Simulator,name=iPhone 7,OS=10.0'|ocunit2junit
echo All Done!!
主要是使用的xcodebuild 中的test
xcodebuild test
-workspace $WS
-scheme GFAutoTestDemo_XinMa
-sdk iphonesimulator10.0 -destination 'platform=iOS Simulator,name=iPhone 7,OS=10.0'
各项所代表的内容可以参考http://www.jianshu.com/p/3f43370437d2
可能大家注意到了在这端命令的后面出现了一个ocunit2junit
# OCUnit2JUnit是将OCUnit或Kiwi的输出转换为JUnit使用的格式的脚本。主要目的是能够解析基于Java的构建服务器(如Jenkins)上的Objective-C(OCUnit)测试用例的输出。
地址:https://github.com/ciryon/OCUnit2JUnit/
安装方法:gem install ocunit2junit
1.选择
2.选择后会出现
3.将test-reports/*.xml输入,这样在编译之后会在工程的根目录生成一个 test-reports 的文件夹,里面包含的是测试结果的xml文件
在编译之后在会在工程页面生成
这样就可以在这里对测试结果进行查看。
====================================邮件通知======================================
邮件通知是在自动编译或者自动测试之后对结果对指定的邮箱发送邮件进行通知 这里我们用到的不是jenkins
自带的email-notification 而是使用的第三方的插件email-ext
1.在系统配置中对email进行相关内容的配置
根据提示的相关内容进行填写。由于公司对邮箱进行了限制如果想测试可以向运维进行申请
#参考地址http://www.cnblogs.com/zz0412/p/jenkins_jj_01.html
以上是在系统配置中所需要配置的下面我们对项目中的进行配置
2.在构建过后操作步骤选择
则在构建后操作步骤会增加
这在链接中都有提到
我们们的目的是在工程测试后通知我们测试的结果。这里就需要在构建后有这两个操作。以为jenkins支持jelly邮件模板 所以在这里我们需要使用jelly去编写我们
需要的模板。
邮件模板:(这个可以深入研究 只要你想要的参数都可以使用jelly在jenkins里面进行可视化的显示)
]>
BODY, TABLE, TD, TH, P {
font-family:Verdana,Helvetica,sans serif;
font-size:11px;
color:black;
}
h1 { color:black; }
h2 { color:black; }
h3 { color:black; }
TD.bg1 { color:white; background-color:#0000C0; font-size:120% }
TD.bg2 { color:white; background-color:#4040FF; font-size:110% }
TD.bg3 { color:white; background-color:#8080FF; }
TD.test_passed { color:blue; }
TD.test_failed { color:red; }
TD.console { font-family:Courier New; }
BUILD ${build.result}
Build URL${rooturl}${build.url}
Project:${project.name}
Date of build:${it.timestampString}
Build duration:${build.durationString}
Test report:
${project.name} Test Report
Console logs:
${rooturl}${build.url}console
CHANGES
Revision ${cs.commitId?:cs.revision?:cs.changeNumber} by
${aUser!=null?aUser.displayName:cs.author.displayName}:
(${cs.msgAnnotated})
${p.editType.name}
${p.path}
No Changes
0}">
BUILD ARTIFACTS
BUILD ARTIFACTS
${m.key.displayName}
0}">
Health Report
W
Description
Score
${healthReport.description}
${healthReport.score}
Summary Report
Package
Failed
Passed
Skipped
Total
${packageResult.getName()}
${packageResult.getFailCount()}
${packageResult.getPassCount()}
${packageResult.getSkipCount()}
${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()}
${passed_test.getFullName()}
${failed_test.getFullName()}
Note: See attachment also for summary report broken down by classes/methods.
Cobertura Report
Project Coverage Summary
Name
${metric.name}
${coberturaResult.name}
${coberturaResult.getCoverage(metric).percentage}%
(${coberturaResult.getCoverage(metric)})
Source
${coberturaResult.relativeSourcePath}
${coberturaResult.sourceFileContent}
Source code is unavailable
Coverage Breakdown by ${element.displayName}
Name
${metric.name}
${child.xmlTransform(child.name)}
${childResult.percentage}%
(${childResult})
N/A
CONSOLE OUTPUT
${line}
邮件模板编写完成后文档的结尾必须是以 .jelly结尾 并将模板文件保存在
~/.jenkins/email-templates 这个文件夹下以供jenkins调用
3.生成模板后我们需要在构建后步骤中配置,使email-ext能进行调用生成
在Default Content 中 添加${JELLY_SCRIPT,template="myreport"}---------'myreport'为你制作的邮件模板的文件名
4.高级设置
在高级设置中我们可以对发送邮件的条件进行添加,根据你需要发送邮件的条件进行选择添加。触发条件中也有高级选择,则是对发送邮件进行更细化的设置
====================================分割线啊=======================================
以上所有内容参考链接
http://www.cnblogs.com/woniu123/p/6897956.html
http://blog.csdn.net/jiang1986829/article/details/51273967
http://qa.blog.163.com/blog/static/19014700220131011102715643/
http://blog.csdn.net/fullbug/article/details/53024562
http://www.cnblogs.com/zz0412/p/jenkins_jj_01.html
http://blog.csdn.net/ffeiffei/article/details/19761853
http://itfish.net/article/59477.html
http://www.sohu.com/a/70859257_216613
http://blog.csdn.net/dongyu0729/article/details/38847907
====================================分割线啊======================================
以上就是自动测试和触发邮件发送通知的相关内容。由于这部分的内容比较分散,所以只有在实际操作中才能触发
上述内容我司张帆大神总结的。
最后分享一下我jenkins主要配置过程中遇到的一些问题。。。
1:安装 home-brew
/usr/bin/ruby -e "$(curl -fsSLhttps://raw.githubusercontent.com/Homebrew/install/master/install)"
官网 中文:https://brew.sh/index_zh-cn.html
2:安装 报错 could not lock config file /usr/local/Homebrew/.git/config: Permission denied
Press RETURN to continue or any other key to abort
==> Downloading and installing Homebrew...
error: could not lock config file /usr/local/Homebrew/.git/config: Permission denied
fatal: could not set 'core.repositoryformatversion' to '0'
Failed during: git init -q
bojoydeiMac:~ bojoy$ sudo chown -R $USER /usr/local
bojoydeiMac:~ bojoy$ /usr/bin/ruby -e "$(curl -fsSLhttps://raw.githubusercontent.com/Homebrew/install/master/install)"
我这边解决方法是 sudo chown -R $USER /usr/loca
3:配置java环境 brew cask install java
4:Jenkins安装 brew install jenkins
5:安装Jenkins 报错 parent directory is world writable but not sticky
==> Downloading fromhttp://mirrors.tuna.tsinghua.edu.cn/jenkins/war/2.74/jenkin
######################################################################## 100.0%
==> jar xvf jenkins.war
Error: parent directory is world writable but not sticky
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/tmpdir.rb:92:in `mktmpdir'
/usr/local/Homebrew/Library/Homebrew/utils/fork.rb:6:in `safe_fork'
/usr/local/Homebrew/Library/Homebrew/formula_installer.rb:682:in `build'
/usr/local/Homebrew/Library/Homebrew/formula_installer.rb:309:in `install'
/usr/local/Homebrew/Library/Homebrew/cmd/install.rb:336:in `install_formula'
/usr/local/Homebrew/Library/Homebrew/cmd/install.rb:226:in `block in install'
/usr/local/Homebrew/Library/Homebrew/cmd/install.rb:224:in `each'
/usr/local/Homebrew/Library/Homebrew/cmd/install.rb:224:in `install
原因:/tmp目录权限不对 解决办法:$ sudo chmod +t /tmp (注解:chmod +t+t 表示设置粘着位(sticky bit),防止文件或目录被非属主删除)
6:启动 jenkins:jenkins
启动过程中强制关闭后
再次启动 jenkins会报错
Container startup failed
java.io.IOException: Failed to start Jetty
at winstone.Launcher.(Launcher.java:156)
at winstone.Launcher.main(Launcher.java:354)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
是因为 jenkins默认端口号8080被占用
这里可以
Mac下命令关闭Jenkins
使用ps命令找到Jenkins的pid号
命令:ps
PID TTY TIME CMD
21403 ttys002 0:00.10 /System/Library/Frameworks/Ruby.framework/Versions/2.0
24818 ttys002 0:21.79 /usr/bin/java -jar /usr/local/Cellar/jenkins/2.74/libe
92791 ttys002 0:00.11 -bash
干掉这个pid, 就可以关闭Jenkins
kill -9 24818 (注释 命令:kill -Signal pid 其中:pid是进程号,可以用 ps 命令查出signal是发送给进程的信号,TERM(或数字9)表示“无条件终止)
Jenkins is fully up and running
这个就代表成功了 然后本地打开http://localhost:8080/jenkins/
gitlab hook 失败 有可能URL写的不对,url应该写成自己电脑的ip地址
还有根据文档学习,发现自己本地jenkins有些配置和图中不一致,那就有可能自己有些插件忘了下载了切记切记,比如构建触发器的时候没有Build
when a change is pushed to GitLab 这个选项,我当时郁闷了有一会,记得下载相关gitlab插件