教学仓库: https://github.com/jinxuanzheng01/blog-xcx-ci-demo/tree/master,可以clone下来跟着教程 一起尝试,

CI流程搭建教学三部曲:

背景

相信长期在做小程序的同学都有过以下经历:

  • 只有固定的几台机器能发版,换台机器总担心出现点问题 (心力成本)
  • 多个小程序发版,切换多个仓库,甚至要用开发者工具去打开不同的项目(体力成本)
  • 频繁发版 + 发版流程琐碎 + 可能存在的多个小程序,一天的时间被机械劳动的事耗掉半天(时间成本)

本文主要来分享一下我这边的一套解决,实现一键发布,统一管理,在读之前最好先看下上一篇文章,不然可能会有些阻碍

关于jenkins:https://www.jenkins.io/zh/

案例

image.png
这个是目前我们已经搭建好的一套服务,可以看到整个流程都做了那些事?

  • 拉取代码
  • 询问当前需要变更的版本号
  • 构建(gulp, webpack,npm)
  • 存储当前版本镜像到静态资源服务器
  • 版本信息插入数据库
  • 更改后的版本文件提交到git仓库

其中红色为必须项,黑色看情况添加,如果你想也可以加入你想要添加的任何环节,下图是我们的版本发布管理后台的界面,存储的mysql的版本信息大概是这个样子:

image.png
关于管理后台第三章再讲,本文先着重描述怎么接入jenkins

Let’go

首先你需要一台云服务器用来搭建jenkins环境,推荐2核4g,不过1核2g也能跑

安装java

jenkins依赖于java环境,所以先安装java

  1. yum install -y java-1.8.0-openjdk.x86_64

安装jenkins包

官方教程: https://www.jenkins.io/zh/doc/book/installing/
仓库地址: http://pkg.jenkins-ci.org/redhat-stable/

  1. sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
  2. sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
  3. yum install jenkins
  4. # 运行
  5. service jenkins start

运行成功后访服务器端口号8080image.png如果想修改端口号 vim /etc/sysconfig/jenkins, 找到JENKINS_PORT,修改后执行 service jenkins restart 即可
image.png
关于插件安装个人比较懒,点推荐快速过,后面有用到的一些插件慢慢会介绍
image.png
插件装完,中间需要创建管理员账号,一路确定最终安装成功
image.png

创建流水线pipeline

首先创建一个任务, 这里选择流水线(有兴趣可以了解下其他项), 点击确定
image.png
点击流水线找到编辑script的地方
image.png
image.png
这里可以选择在服务器上编写,还是从项目代码中读取jenkinsfile文件,我这里为了方便调试直接在jenkins机器上编写了

pipeline script

流水线语法官方教程: https://www.jenkins.io/zh/doc/book/pipeline/,里面讲的比较详细,可以先按下面的代码运行,遇到问题再查教程

流水线结构

写流水线之前,先想好我们整个发布流程需要做什么?
以当前例的话,大致分为5个环节:

  • 拉取代码
  • 询问需要更改的版本号
  • 安装npm包
  • 执行发布
  • 提交修改的版本号信息到仓库

每一个环节都是一个stage,先把stage列好,接下来我们一个一个补充

  1. pipeline {
  2. agent any
  3. stages {
  4. // 拉取git代码
  5. stage('git pull') {
  6. steps {
  7. }
  8. }
  9. // 询问当前版本信息
  10. stage('inquirer version') {
  11. steps {
  12. }
  13. }
  14. // 构建
  15. stage('build') {
  16. steps {
  17. }
  18. }
  19. // 推送版本信息到git仓库
  20. stage('push version2git') {
  21. steps {
  22. }
  23. }
  24. }
  25. }

流水线语法

很多插件的语法使用还是比较复杂和琐碎的,这里提供了一个自动生成pipieline语法的功能
image.png
以git为例,会自动生成相应的语法,避免很多查文档的时间
image.png

拉取git代码

根据上文所述,我们需要生成流水线脚本,但是想要让仓库和jenkins建立ssh链接,需要配置git仓库的公钥和jenkins的私钥凭据

配置git仓库公钥

jenkins拉取git仓库代码,为了方便需要配下ssh秘钥

  1. # 生成秘钥(没有要求一路回车即可)
  2. ssh-keygen -t rsa -C "616347058@qq.com"
  3. # 查看生成的ssh文件
  4. cd ~/.ssh && ls # 一般会有id_rsa id_rsa.pub两个文件, 一个私钥一个公钥

点击个人头像点击setting找到ssh,粘贴 id_rsa.pub 里的内容到输入框,点击add添加完成
image.png
image.png

配置jenkins私钥

除了在git上配置公钥外,还需要在jenkins上配置下凭据,点击添加
image.png
选择类型为ssh username,其他input的可以自己定一下的,这里需要一下,关于private项填的是私钥,需要复制id_rsa的内容,填写完成后点击添加,并在 Credentials 一栏选择刚才添加的证书
image.png
当前页面没有显示红字即为成功
image.png

pipeline code

  1. // 拉取git代码
  2. stage('git pull') {
  3. steps {
  4. git branch: 'test', credentialsId: '1', url: 'git@github.com:jinxuanzheng01/blog-xcx-ci-demo.git'
  5. }
  6. }

添加到指定位置后,点击保存,尝试构建一次查看是否成功,点左下角#5可以查看当前构建进程
image.png
点击console output可以查看当前log,workspaces可以查看当前工作空间
image.png
可以看到当前工作空间为仓库代码
image.png

询问当前版本信息

jenkins是不支持交互式命令的,所以需要换一种实现,查了下文档jenkins是有api支持的,方法名为 input,不过在进行调用之前需要获取之前的版本信息,即读取version.config.json这个文件,整体代码如下:

  1. // 询问当前版本信息
  2. stage('inquirer version') {
  3. steps {
  4. script {
  5. // 读取版本信息
  6. def versionJson = readJSON file: './version.config.json', text: ''
  7. // 设置问题描述
  8. def userInput = input(
  9. id: 'versionInput',
  10. message: '请设置版本信息',
  11. parameters: [
  12. [defaultValue: versionJson.version, description: '设置版本号', name: 'VERSION', $class: 'TextParameterDefinition'],
  13. [defaultValue: 'jenkins CI is upload trial version as: ' + new Date().format('yyyy-MM-dd HH:mm:ss'), description: '设置版本描述(please use english)', name: 'VERSIONDESC', $class: 'TextParameterDefinition']
  14. ])
  15. // 设置全局变量
  16. env.VERSION = userInput.VERSION;
  17. env.VERSIONDESC = userInput.VERSIONDESC;
  18. // 重写本地版本文件(为后续进行版本提交做准备)
  19. writeJSON file: './version.config.json', json: [version: env.VERSION, versionDesc: env.VERSIONDESC], pretty: 4;
  20. }
  21. }
  22. }

运行下, 会发现会提示等待,鼠标点击后弹出模态框,可以看到里面有从本地文件里提取出来的上个版本的信息,手动修改下即可
image.png
注: readJSON和 writeJSON方法依赖 Pipeline Utility Steps 这个插件,没有的话会报错

执行构建

这里实际都是构建流程,直接统一用一个“build stage” 即可, 这里步骤很简单,可以想一下从git clone下来一个项目应该干什么,这里实际就是在做这样一件事情

  1. // 构建
  2. stage('build') {
  3. steps {
  4. sh "npm install"
  5. sh "npm run build"
  6. }
  7. }

不过这里依赖node环境,需要先处理下,不然会报npm not found

安装nodejs环境

这里的运行环境和本机没有关系,类似于一个沙盒,所以如果要安装node环境需要安装Config File Provider PluginNodeJS Plugin这两个插件

配置全局工具

安装完成后添加全局工具,找到”系统管理 -> 全局工具配置 -> NodeJS“ ,点击nodejs安装,默认项即可,点击保存,重启jenkins服务,回到服务器,输入命令 service jenkins restart
image.png

pipeline code

  1. // 构建
  2. stage('build') {
  3. steps {
  4. nodejs('NodeJS 14.3.0') {
  5. sh "npm install"
  6. sh "npm run build"
  7. }
  8. }
  9. }

上传成功

这时候如果没问题的话代码应该已经发布到体验版了,
这里如果报ip错误记得去微信公众后台添加一下上传的ip白名单
image.png

image.png

提交新的版本号信息到仓库

pipeline code

基本就是将之前手动输入的命令写到脚本里

  1. // 推送版本信息到git仓库
  2. stage('push version2git') {
  3. steps {
  4. sh "git config --local user.name ${GIT_USER_NAME} && git config --local user.email ${GIT_USER_EMAIL}"
  5. sh "git add version.config.json"
  6. sh "git commit -m 'docs: 更改版本号为${VERSION}'"
  7. sh "git push origin ${BRANCH_NAME}"
  8. }
  9. }

关于上面代码中的”${}”,其实是预设的环境变量,我们可以把一些固定的东西提出来,避免硬编码,例如:

  1. pipeline {
  2. agent any
  3. // 环境变量
  4. environment {
  5. GIT_USER_NAME = 'jenkinsCI'
  6. GIT_USER_EMAIL = 'test@163.com'
  7. GIT_ADDRESS = 'git@github.com:jinxuanzheng01/blog-xcx-ci-demo.git'
  8. BRANCH_NAME = 'master'
  9. }
  10. }

更改jenkins账号权限

直接进行push的话,git会报权限不足,这里倒不是因为ssh秘钥有问题,而是jenkins在执行的时候使用的不是linux机器的root权限,而是一个jenkins的账号
image.png
所以最快速的做法是将jenkins运行环境修改为root权限

  1. # 打开配置文件
  2. vim /etc/sysconfig/jenkins
  3. # 修改jenkins_user为root, 默认为jenkins
  4. $JENKINS_USER="root"
  5. # 修改相关文件夹权限组
  6. chown -R root:root /var/lib/jenkins
  7. chown -R root:root /var/cache/jenkins
  8. chown -R root:root /var/log/jenkins
  9. # 重启jenkins
  10. service jenkins restart

运行pipeline

重新构建,jenkins无报错,查看git仓库,执行成功
image.png

Running success

到此为止,整个pipeline已经work,你可以很轻松的尝试一键发布小程序
image.png
尤其是有多个小程序项目的时候,可以单独建个分组,方便集中管理,再也不需要手动切入不同的仓库,甚至使用小程序开发者工具去打开各个小程序,大概如下
image.png
项目集中管理不香么?

Tips: jenkins流水线代码已经放到仓库里了,地址 https://github.com/jinxuanzheng01/blog-xcx-ci-demo/blob/master/Jenkinsfile

额外补充

权限管理

jenkins有很多的功能插件,比如权限管理,这个还是个比较刚需的功能,可以自行Google下并不难

发送http请求

在pipeline中有时候需要去请求一些我们的其他服务,可以使用HTTP Request Plugin这个插件,文档地址:https://plugins.jenkins.io/http_request/里面有一些demo

npm切换私有仓库

方法一: npm可以直接用npm_token登录
方法二:项目内设置.npmrc,填写私有仓库 + 用户信息

jenkins使用docker报权限不足

image.png
修改jenkins账号权限为root权限即可,上文有写,也可以直接修改docker.sock这个文件权限,如 chmod 777 /var/run/docker.sock

手动安装jenkins插件

使用jenkins的插件管理安装插件很慢,有的时候还会失败,这里提供一个手动安装的方法

jenkins插件库: http://updates.jenkins-ci.org/download/plugins/config-file-provider/
搜索需要的插件下载(一般是*.hpi格式的),打开jenkins “系统管理 -> 插件管理 -> 高级”,选择下载的文件上传即可
image.png