pipeline的定义

  简而言之,就是一套工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排与可视化。
  目前比较流行的pipeline实践方式如下。

  • gitlabrunner: 是gitlab内置的一套pipeline框架,脚本是yml语言。
  • jenkins: 通过安装插件的形式实现,脚本语言是jenkinsfile。

由于团队中的代码仓库没有使用gitlab,因此我这边选择了jenkins来实践pipeline。

什么是jenkinsfile

  jenkinsfile 就是一个脚本文件,放在项目的根目录下,能够被jenkins识别并自动触发pipeline流程,jenkinsfile的编写可以参考jenkins官网:jenkinsfile语法

pipeline一期目标

  团队第一期目标是:实现开发pod库时提交代码自动触发单元测试,不同分支能执行不同的策略,执行不同的pipeline任务,能够自动发布pod。pipeline失败时能够发送邮件进行通知,pipeline流成如下:

jenkins pipeline 容器内 jenkins pipeline使用_pod发布


jenkinsfile 脚本如下:

pipeline {
  agent any

  parameters {
     string(name: 'PROJECT_NAME', defaultValue: 'test_rootlib_ios', description:'')
  }

  stages {
    stage('prepare') {
      steps {
          sh './ci_prepare.sh' 
      }
      post {
          failure {
            post_email('prepare','fail')
          }
          aborted {
            post_email('prepare','aborted')
          }
      }
    }

    stage('unit_test') {
      steps {
        sh './ci_unit_test.sh'
      }
      post {
          failure {
            post_email('unit_test','fail')
          }
          aborted {
            post_email('unit_test','aborted')
          }
      }
    }

    stage('lib_lint') {
       when {
          branch 'dev'
       }
       steps {
          sh './lib_lint.sh'
       }
       post {
          failure {
            post_email('lib_lint','fail')
          }
          aborted {
            post_email('lib_lint','aborted')
          }
       }
    }

    stage('publish_pod') {
      when {
          branch 'dev'
       }
       steps {
          sh './repo_tag.sh'
       }
      post {
          failure {
            post_email('publish_pod','fail')
          }
          aborted {
            post_email('publish_pod','aborted')
          }
      }
    }
    stage('pipeline_end') {
      when {
          branch 'dev'
      }
      steps {
          echo 'pipeline_end'
      }
      post {
          success {
            post_email('pipeline_end','success')
          }
          failure {
            post_email('pipeline_end','fail')
          }
          aborted {
            post_email('pipeline_end','aborted')
          }
      }
    }

  }

}

def post_email(String stage, String status) {
  mail to: '12345678@qq.com',
  subject: "【${PROJECT_NAME}】${stage} ${status}",
  body: "build_id: ${env.BUILD_NUMBER}\nbranch: ${env.GIT_BRANCH}\nstage: ${stage}\nbuild_url: ${env.BUILD_URL}"
}

脚本思路:
1,每次提交时都会触发pipeline,首先执行准备阶段的任务主要是清理环境,pod install之类的操作。然后触发单元测试。测试成功后没有任何提示,测试失败时会通过邮件进行通知
2,dev分支是发版分支,当pod准备要发布时,将版本号改好,然后先执行prepare阶段的任务,然后执行单元测试,接着执行pod lint的任务,然后执行发版的操作,发版成功后会发送邮件进行通知。ps:后期会执行项目自动集成相关的工作。

blueOcean

blueOcean 是jenkins提供的可视化的形式编辑jenkinsfile的一个插件,大家可以体验下,这里就不多说了,感觉刚开始入门的时候可以试试,可视化没有直接在脚本上编辑流程灵活。
参考网址:blueOcean

遇到的坑点

邮箱

  在最开始的实践是,本来打算用公司的邮箱进行通知,后来发现公司的邮箱不支持类似配置。我这边选择了163邮箱配置在jenkins上进行通知。

bundle exec命令

由于团队中对组件化进行预编译,实现了二进制形式的集成,在准备阶段执行如下命令的时候一直报错

bundle config set deployment 'true'
bundle install
bundle exec pod install --repo-update

后来参考网上,在jenkins进行了全局环境变量配置。

jenkins pipeline 容器内 jenkins pipeline使用_单元测试_02

内存不足

  最开始时候设置了pipeline的配置,当分支删除时,对应的pipeline构建会被删除,但是由于电脑配置太差,加上分支较多,出现了内存不足的现象。直接造成jenkins坏掉了,为了解决这个问题,我在jenkinsfile上写了一个脚本定期去删除项目中各个分支中的构建。

jenkins pipeline 容器内 jenkins pipeline使用_单元测试_03

脚本具体如下:

#!/bin/bash
cd ..
cd ..
cd jobs
projects=("项目名字" "项目名字" "项目名字" "项目名字")
for project in ${projects[*]}
do
#进入对应项目目录
  cd $project
  project_dir=$(pwd)
  echo "project dir is:$project_dir"
  cd branches
  pwd=`pwd`
  filelist=`ls $dir`
  for biranch in $filelist:
  do
  #进入对应项目分支目录
    cd biranch
    rm -rf builds
    mkdir builds
    cd ..
  done
  
  cd ..

done