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

登录

https://localhost:8080

首次使用设置

该处的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


${f}



BUILD ARTIFACTS

${m.key.displayName}

0}">


${f}


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)"

报错参考https://apple.stackexchange.com/questions/42127/homebrew-permissions-multiple-users-needing-to-brew-update

我这边解决方法是 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插件

推荐阅读更多精彩内容