美文网首页持续集成iOS 宝典iOS开发
使用GitLab来实现IOS项目的持续集成CI

使用GitLab来实现IOS项目的持续集成CI

作者: cjzhao | 来源:发表于2016-08-03 13:05 被阅读8473次

    作为程序员,代码是一定要写的,而且要天天写。在好多地方见过这样一种说法:

    只会写程序的程序员不是好程序员

    当然,我不赞同这种观点,因为有的人他天生就是为程序而生的。但是掌握一些代码之外的理论知识也是一个不错的选择,它能让你的代码质量上一个新的台阶,能极大的提高你的“抠码”效率。

    最近新的APP即将上线,但在产品、研发、运营几个环节出了一些问题,也让我静下心来思考一些一个程序员觉得很难直面的问题。这其中和技术相关的问题包括:

    • APP版本更新较为频繁的问题。

    • 测试覆盖不到位的问题。

    APP的开发可能跟以前我所经历的大部分企业级应用软件、IaaS/PaaS平台、大数据平台相关产品完全的不同,为了响应市场需求,APP的迭代周期要以周为单位(打开手机看看常用 的APP大部分每周一更新),IOS还受到苹果审核周期的影响,会有更多的不可控因素。为了解决这些问题,目前我们主要做的工作包括几个方面:

    • 解决运营和产品环节的反馈机制问题。

    • 优化APP的打包、测试的方式。

    • 合理的制定版本发布计划。

    今天想给技术人员分享的主要就是持续集成和交付/部署(CI/CD)方面的一些基础知识,同时结合我们现在正在开发的APP中遇到的一些问题,和大家共同探讨如何才能更好的优化我们的产品打包、测试过程。

    持续集成和持续交付/部署 CI/CD

    Continuous Integration (CI) is a development practice that requires developers to integrate code into a shared repository several times a day. Each check-in is then verified by an automated build, allowing teams to detect problems early.

    By integrating regularly, you can detect errors quickly, and locate them more easily.

    上面对CI的�定义参考 thoughtworks,可能把它生硬的翻译过来也不太好理解,我从这些年的产品研发过程中见到过的各种CI工具来定义CI的话,可以做如下定义:

    CI是软件(产品)研发生命周期中对代码质量、系统集成的一个持续构进的过程,当作为一个团队开发产品时,每个人都要开发自己的功能模块,最终都需要集成在一起,代码也需要集中托管到同一个地方,通过使用一些自动化的代码打包、测试工具,能够在开发人员每提交一次代码的时候,系统自动对程序进行打包和单元测试,如果出现问题,及时通过邮件等方式通知相关的开发人员。

    5年前,我还在从事企业级应用软件的开发,那时根本就没有什么单元测试,更没有自动打包、测试的工具,也就大家开发完功能,提交到SVN服务器,还有一个专业的人在需要打包里把代码down下来在自己机器上打包,然后部署到测试环境跑一把,没什么大问题就上生产环境。现在想想还是真“土”。

    这几年,我和我的团队主要是基于openstack开发一款企业级的云管理平台,从一开始的懵懵懂懂,到现在形成比较成熟的基于CI的整个开发流程,也爬过了一个又一个的坑和坎。

    目前我们比较成熟的套路是: _ git+gerrit+jenkins _

    其中git用于代码托管,gerrit主要是是代码的评审,jenkins用于打包和跑单元测试。这样的组合百度一下,会有很多先辈们已经写了很多博客和文章,我这里就不在烂费精力了。今天我想介绍一下的是目前我们的APP开发过程中想采用的gitlab。要不然大家都觉得我写的东西没干货,也不好意思啊。

    GitLab

    GitLab是一个集代码管理、测试、代码部署于一体的开源应用程序,它包括一个有非常好的权限控制的Git版本管理系统,代码评审系统,问题跟踪系统,活动反馈系统,wiki,持续集成CI系统等。

    上面的翻译可能有点别扭,没办法,我就这水平了,咱们直接进入正题吧。

    我个人比较喜欢的就是gitlab长的太像github了,使用很方便,同时采用了github的pull request方式来对代码进行审核,还集成了CI(虽然大部分还是要看你写脚本的水平如何)。

    我将通过使用一个ios的demo项目来给大家展示如何用gitlab来管理代码、进行代码审核、CI等等。

    安装GitLab

    在Docker盛行的今天,我也就偷偷懒,跑个docker实例给大家演示一下,如果您在打算在生产环境使用gitlab,可以参考官方的安装文档,包括一些集群方案都能找到。用Docker跑gitlab就一个命令:

    这里假设我们的服务器IP是:47.88.21.77 一定要记得根据您的实际情况更改IP地址哦。

    
    sudo docker run --detach --hostname gitlab.example.com --env GITLAB_OMNIBUS_CONFIG="external_url 'http://47.88.21.77/'; gitlab_rails['lfs_enabled'] = true;" --publish 443:443 --publish 80:80 --publish 22:22 --name gitlab --restart always --volume /srv/gitlab/config:/etc/gitlab --volume /srv/gitlab/logs:/var/log/gitlab --volume /srv/gitlab/data:/var/opt/gitlab gitlab/gitlab-ce:latest
    
    

    服务启动后,浏览器进入:http://47.88.21.77/

    gitlab_login.png

    首次进入可以设置root的密码,注册用户即可进入系统,这里我们演示时使用的用户名是cjzhao,登录后如下图所示:

    gitlab_firstpage.png

    空空如也……

    使用gitlab评审代码

    在这里可以创建组织、项目,基本概念和github一样,这里我们直接创建我们要演示的项目ios_ci_demo。

    gitlab_newproject.png

    OK,多的不解释了,一看就懂。

    gitlab_projecthome.png

    创建完成后,进入项目首页,看到黄色的提示信息了吧,为了能从远程把代码推到服务器,需要配置一个ssh公钥,点击add an SSH key把你自己的公钥添加完成,就可以把代码上传上去了,这个过程就不截图了哦,看到我的公钥也不是太好……呵呵。

    添加完公钥后,回到项目首页,如下图所示:

    gitlab_codeuploadmethod.png

    我们根据第三种方法把现有的代码上传到gitlab,即执行下面的代码:

    cd existing_folder
    git init
    git remote add origin git@47.88.21.77:cjzhao/ios_ci_demo.git
    git add .
    git commit
    git push -u origin master
    

    我们的app很简单,如下图所示:

    Simulator_hello.png

    很明显, word是错的哦,后面我们将演示另一个用户修改完后提交代码,并做代码审核。

    上传完代码后,进入项目首页,如下图所示:

    gitlab_project_home_first.png

    再注册一个新用户jack,然后用cjzhao登录后,进入项目设置页面(如下图所示),把jack增加到项目中,这样他就能提交代码了。

    gitlab_project_setting_menu.png

    添加的过程自己研究吧,很简单,要不编辑会认为我的文章就靠截图凑数了。加完后如下图所示:

    gitlab_add_user_to_project.png

    OK了,接下来用用户jack修改代码,并提交到git服务器。

    jack的操作主要包括以下几个步骤:

    git clone git@47.88.21.77:cjzhao/ios_ci_demo.git
    �git checkout -b wordbug
    //将word改为world
    git add .
    git commit -m "change word to world"
    git push origin wordbug
    

    这时jack登录系统后,会看到提交的代码,同时系统会提示您创建一个Merge request,如下图所示:

    gitlab_create_merge_request.png

    点击Create Merge Request,填写一些修改内容的描述信息,请求cjzhao将代码合并到master即可提交。

    cjzhao登录系统后就能看到jack请求合并的分支,如下图所示:

    gitlab_accept_merge_request.png

    在完成代码评审后,点击Accept Merge Request即可将代码合并到master。选中Remove source branch同时将wordbug分支删除。

    OK,这就完成了多开发人员合作的项目代码评审流程。

    gitlab中的CI

    在gitlab中完成持续集成CI包括两个操作:

    • 配置一个Runner(用来编译、测试、打包的服务器节点)。

    • 在项目根目录增加YAML格式的CI脚本文件.gitlab-ci.yml

    配置Runner

    我们首先来为我们的项目配置一个Runner,由于我们的项目是ios的,因此需要在安装了macos操作系统和xcode的环境下才能编译、打包我们的APP,因此我们需要将一台mac计算机配置成我们的一个Runner,基本原理就是在Mac上安装一个代理程序gitlab-ci-multi-runner,然后将mac注册到gitlab服务器端,然后这台mac机器就能接收到gitlab服务器下发的CI任务,完成相应的编译、测试、打包等工作,然后将结果反馈给gitlab服务器。

    在一台Mac机器上执行如下命令安装gitlab-ci-multi-runner(可能需要翻墙才能装哦):

    sudo curl --output /usr/local/bin/gitlab-ci-multi-runner https://gitlab-ci-multi-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-ci-multi-runner-darwin-amd64
    
    sudo chmod +x /usr/local/bin/gitlab-ci-multi-runner
    

    进入项目的Runner配置页面,如下图所示:

    gitlab_config_runner.png

    在Mac机器上执行如下命令,将这台Mac注册到gitlab并绑定到我们示例项目。

    gitlab-ci-multi-runner register
    #Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/ci):
    #输入上图中的URL.
    #Please enter the gitlab-ci token for this runner:
    #�输入上图中的token.
    #Please enter the gitlab-ci description for this runner:
    #输入一个描述信息,这里我们输入mac_runner
    #Please enter the gitlab-ci tags for this runner (comma separated):
    #�输入一些标签,这里我们输入"mac,xcode7.1"
    # Registering runner... succeeded runner=euasz2j9 
    #Please enter the executor: docker-ssh+machine, docker, docker-ssh, parallels, shell, ssh, virtualbox, docker+machine:
    #这里我们输入shell,因为ios项目的编译、测试、打包我们都采用脚本来执行。
    #Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
    #注册成功,接下来启动它
    gitlab-ci-multi-runner install 
    gitlab-ci-multi-runner start
    

    现在我们的Mac机器就注册为一个Runner了,查看项目的Runner页面,如下图所示:

    gitlab_runner_running.png

    我们的Runner就成功注册上了。接下来就可以编写CI的脚本了。

    增加CI脚本文件.gitlab-ci.yml

    在项目根目录创建.gitlab-ci.yml文件,内容如下:

    stages:
      - build
      - archive
    
    build_project:
      stage: build
      script: 
        - xctool -project ioscidemo.xcodeproj -scheme ioscidemo clean
        - xctool -project ioscidemo.xcodeproj -scheme ioscidemo test -test-sdk iphonesimulator9.3
    
    archive_project:
      stage: archive
      script: 
        - xctool -project ioscidemo.xcodeproj -scheme ioscidemo archive -archivePath build/ioscidemo
        - xcodebuild -exportArchive -exportFormat ipa -archivePath "build/ioscidemo.xcarchive" -exportPath "build/ioscidemo.ipa"
      only: 
        - master
      artifacts:
        paths:
          - build/ioscidemo.ipa
    

    上面脚本使用了xctool,它是facebook推出的一款替代xcodebuild的app打包和测试工具,它日志输出更加友好,性能高效,我们需要在刚才安装了Runner的Mac机器上先安装它,可以使用如下命令安装:

    
    brew install xctool
    
    

    OK,接下来就是提交我们最新的代码了:

    
    git add .
    
    git commit -m "add CI cfg file"
    
    git push origin master
    
    

    如果没有什么异常的话,CI已经在开始执行编译、测试、打包等工作了。见下图所示:

    gitlab_project_build_status.png

    看到绿色的passed了吧?这就说明编译、测试、打包都成功了(我可是耗费了好长时间才成功的哦,中间总会出现各种各样的问题)。就写到这儿吧,最后再给大家提供一点CD的思路(技术层面的),刚才的过程已经完成了app的打包,我们可以创建一个Releases的分支,在脚本中增加APP上传到itunesconnect的脚本,这样就可以在发布新版本的时候完成APP的整个发布流程。

    Apple给我们提供了一套命令行工具altool可以直接把ipa上传到itunesconnect,很方便的,详见:用 altool 上传您的应用程序二进制文件

    OK,真的结束了,自己去研究吧。

    希望本文对您有所帮助,谢谢。


    CJ推荐:
    程序员的编辑器-VIM(爱就是爱)
    向开源社区贡献您的代码
    在github上写博客
    DevOps是什么东东?
    js依赖管理工具bower
    JS模块化编程-requirejs

    相关文章

      网友评论

      • 小狐记忆:想问一下,
        1,开发者请求是直接合并到master分支吗?git push代码后运维应该是怎么样发布的流程?master是指正式发布的环境,那预生成环境应该在哪个环节?
        2,gitlab的CI/CD这项功能,在jenkins上能够很快速的实现,为什么还要使用gitlab来进行CI/CD?
      • e997782fc29c:build_project:
        stage: build
        only:
        - master
        except:
        - feature
        - develop

        为什么每次往develop和feature上提交代码的时候build这个job还执行呢?
      • baef91c74426:Running with gitlab-ci-multi-runner 9.5.0 (413da38)
        on mac_runner (de7cbe25)
        Using Shell executor...
        Running on xxxxxMacBook-Pro.local...
        Cloning repository...
        Cloning into '/Users/xxxxxxx/builds/de7cbe25/0/xxxx/xxxxxxx-iOS'...
        fatal: unable to access 'http://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@localhost:8088/xxxx/xxxxx-iOS.git/': Failed to connect to localhost port 8088: Connection refused
        ERROR: Job failed: exit status 1

        楼主 CI一致报这个错 怎么搞
        cjzhao:把防火墙关了试试
      • 8d0946d22d41:请教下:
        gitlab ci这台机器是单独另外一台机器,还是就在代码所在本机,如果不是在本机,那么在push的时候自动构建,另外一台机器需要先拉取代码 才能构建吧。
        cjzhao:可以参考http://www.jianshu.com/p/ab359978d083?utm_campaign=hugo&utm_medium=reader_share&utm_content=note
        8d0946d22d41:@cjzhao 那怎么达到自动部署呢
        cjzhao:不需要在本机,client会自动拉取最新代码
      • 洋洋丝:厉害了,赞一个。大致都看懂了,就是脚本那块没看懂,在项目根目录里创建yml文件,那么是只要我push了就构建吗还是如何
        cjzhao:@洋洋丝 push后自动构建
        洋洋丝:脚本文件内容希望能讲的详细一些
      • fir_im官方:厉害!!Automating shapes smarter future.
        楼主也来体验一下 flow.ci 的 iOS 持续集成;
        https://flow.ci
      • 4c2eb92b993f:为什么在本机通过的命令,到了 gitlab ci 上就报错呢,说找不到 scheme,还有什么玄机吗
        Chipmuck:manage Schemes -> Shared
        cjzhao:@GoldenanNull 可能是用户权限问题
      • 若非长得丑怎会做逗比:你好!

        stages:
        - build

        build_project:
        stage: build
        script:
        - xcodebuild clean -workspace ShowStart_3.0.xcworkspace -scheme ShowStart_3.0
        - xcodebuild build -workspace ShowStart_3.0.xcworkspace -scheme ShowStart_3.0

        这是我的yml 文件 pip 哪里看到 一直在转圈
      • Arxu:写的很清晰!赞
      • 知傲:相对来说还是Jenkins功能强大灵活

      本文标题:使用GitLab来实现IOS项目的持续集成CI

      本文链接:https://www.haomeiwen.com/subject/tlmqsttx.html