教学仓库: https://github.com/jinxuanzheng01/blog-xcx-ci-demo/tree/master,可以clone下来跟着教程一起尝试
CI流程搭建教学三部曲:
- 实现云构建
- 如何接入CI(jenkins版)
- 搭建一个版本发布管理后台 + 企业微信机器人群通知
背景
相信长期在做小程序的同学都有过以下经历:
- 只有固定的几台机器能发版,换台机器总担心出现点问题 (心力成本)
- 多个小程序发版,切换多个仓库,甚至要用开发者工具去打开不同的项目(体力成本)
- 频繁发版 + 发版流程琐碎 + 可能存在的多个小程序,一天的时间被机械劳动的事耗掉半天(时间成本)
本文主要来分享一下我这边的一套解决,实现一键发布,统一管理,在读之前最好先看下上一篇文章,不然可能会有些阻碍
关于jenkins:https://www.jenkins.io/zh/
案例
这个是目前我们已经搭建好的一套服务,可以看到整个流程都做了那些事?
- 拉取代码
- 询问当前需要变更的版本号
- 构建(gulp, webpack,npm)
- 存储当前版本镜像到静态资源服务器
- 版本信息插入数据库
- 更改后的版本文件提交到git仓库
其中红色为必须项,黑色看情况添加,如果你想也可以加入你想要添加的任何环节,下图是我们的版本发布管理后台的界面,存储的mysql的版本信息大概是这个样子:
关于管理后台第三章再讲,本文先着重描述怎么接入jenkins
Let’go
首先你需要一台云服务器用来搭建jenkins环境,推荐2核4g,不过1核2g也能跑
安装java
jenkins依赖于java环境,所以先安装java
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/
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
yum install jenkins
# 运行
service jenkins start
运行成功后访服务器端口号8080
如果想修改端口号 vim /etc/sysconfig/jenkins, 找到JENKINS_PORT,修改后执行 service jenkins restart
即可
关于插件安装个人比较懒,点推荐快速过,后面有用到的一些插件慢慢会介绍
插件装完,中间需要创建管理员账号,一路确定最终安装成功
创建流水线pipeline
首先创建一个任务, 这里选择流水线(有兴趣可以了解下其他项), 点击确定
点击流水线找到编辑script的地方
这里可以选择在服务器上编写,还是从项目代码中读取jenkinsfile文件,我这里为了方便调试直接在jenkins机器上编写了
pipeline script
流水线语法官方教程: https://www.jenkins.io/zh/doc/book/pipeline/,里面讲的比较详细,可以先按下面的代码运行,遇到问题再查教程
流水线结构
写流水线之前,先想好我们整个发布流程需要做什么?
以当前例的话,大致分为5个环节:
- 拉取代码
- 询问需要更改的版本号
- 安装npm包
- 执行发布
- 提交修改的版本号信息到仓库
每一个环节都是一个stage,先把stage列好,接下来我们一个一个补充
pipeline {
agent any
stages {
// 拉取git代码
stage('git pull') {
steps {
}
}
// 询问当前版本信息
stage('inquirer version') {
steps {
}
}
// 构建
stage('build') {
steps {
}
}
// 推送版本信息到git仓库
stage('push version2git') {
steps {
}
}
}
}
流水线语法
很多插件的语法使用还是比较复杂和琐碎的,这里提供了一个自动生成pipieline语法的功能
以git为例,会自动生成相应的语法,避免很多查文档的时间
拉取git代码
根据上文所述,我们需要生成流水线脚本,但是想要让仓库和jenkins建立ssh链接,需要配置git仓库的公钥和jenkins的私钥凭据
配置git仓库公钥
jenkins拉取git仓库代码,为了方便需要配下ssh秘钥
# 生成秘钥(没有要求一路回车即可)
ssh-keygen -t rsa -C "616347058@qq.com"
# 查看生成的ssh文件
cd ~/.ssh && ls # 一般会有id_rsa id_rsa.pub两个文件, 一个私钥一个公钥
点击个人头像点击setting找到ssh,粘贴 id_rsa.pub
里的内容到输入框,点击add添加完成
配置jenkins私钥
除了在git上配置公钥外,还需要在jenkins上配置下凭据,点击添加
选择类型为ssh username,其他input的可以自己定一下的,这里需要一下,关于private项填的是私钥,需要复制id_rsa
的内容,填写完成后点击添加,并在 Credentials 一栏选择刚才添加的证书
当前页面没有显示红字即为成功
pipeline code
// 拉取git代码
stage('git pull') {
steps {
git branch: 'test', credentialsId: '1', url: 'git@github.com:jinxuanzheng01/blog-xcx-ci-demo.git'
}
}
添加到指定位置后,点击保存,尝试构建一次查看是否成功,点左下角#5可以查看当前构建进程
点击console output可以查看当前log,workspaces可以查看当前工作空间
可以看到当前工作空间为仓库代码
询问当前版本信息
jenkins是不支持交互式命令的,所以需要换一种实现,查了下文档jenkins是有api支持的,方法名为 input
,不过在进行调用之前需要获取之前的版本信息,即读取version.config.json这个文件,整体代码如下:
// 询问当前版本信息
stage('inquirer version') {
steps {
script {
// 读取版本信息
def versionJson = readJSON file: './version.config.json', text: ''
// 设置问题描述
def userInput = input(
id: 'versionInput',
message: '请设置版本信息',
parameters: [
[defaultValue: versionJson.version, description: '设置版本号', name: 'VERSION', $class: 'TextParameterDefinition'],
[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']
])
// 设置全局变量
env.VERSION = userInput.VERSION;
env.VERSIONDESC = userInput.VERSIONDESC;
// 重写本地版本文件(为后续进行版本提交做准备)
writeJSON file: './version.config.json', json: [version: env.VERSION, versionDesc: env.VERSIONDESC], pretty: 4;
}
}
}
运行下, 会发现会提示等待,鼠标点击后弹出模态框,可以看到里面有从本地文件里提取出来的上个版本的信息,手动修改下即可
注: readJSON和 writeJSON方法依赖 Pipeline Utility Steps 这个插件,没有的话会报错
执行构建
这里实际都是构建流程,直接统一用一个“build stage” 即可, 这里步骤很简单,可以想一下从git clone下来一个项目应该干什么,这里实际就是在做这样一件事情
// 构建
stage('build') {
steps {
sh "npm install"
sh "npm run build"
}
}
不过这里依赖node环境,需要先处理下,不然会报npm not found
安装nodejs环境
这里的运行环境和本机没有关系,类似于一个沙盒,所以如果要安装node环境需要安装Config File Provider Plugin和NodeJS Plugin这两个插件
配置全局工具
安装完成后添加全局工具,找到"系统管理 -> 全局工具配置 -> NodeJS" ,点击nodejs安装,默认项即可,点击保存,重启jenkins服务,回到服务器,输入命令 service jenkins restart
pipeline code
// 构建
stage('build') {
steps {
nodejs('NodeJS 14.3.0') {
sh "npm install"
sh "npm run build"
}
}
}
上传成功
这时候如果没问题的话代码应该已经发布到体验版了,这里如果报ip错误记得去微信公众后台添加一下上传的ip白名单
提交新的版本号信息到仓库
pipeline code
基本就是将之前手动输入的命令写到脚本里
// 推送版本信息到git仓库
stage('push version2git') {
steps {
sh "git config --local user.name ${GIT_USER_NAME} && git config --local user.email ${GIT_USER_EMAIL}"
sh "git add version.config.json"
sh "git commit -m 'docs: 更改版本号为${VERSION}'"
sh "git push origin ${BRANCH_NAME}"
}
}
关于上面代码中的"${}",其实是预设的环境变量,我们可以把一些固定的东西提出来,避免硬编码,例如:
pipeline {
agent any
// 环境变量
environment {
GIT_USER_NAME = 'jenkinsCI'
GIT_USER_EMAIL = 'test@163.com'
GIT_ADDRESS = 'git@github.com:jinxuanzheng01/blog-xcx-ci-demo.git'
BRANCH_NAME = 'master'
}
}
更改jenkins账号权限
直接进行push的话,git会报权限不足,这里倒不是因为ssh秘钥有问题,而是jenkins在执行的时候使用的不是linux机器的root权限,而是一个jenkins的账号
所以最快速的做法是将jenkins运行环境修改为root权限
# 打开配置文件
vim /etc/sysconfig/jenkins
# 修改jenkins_user为root, 默认为jenkins
$JENKINS_USER="root"
# 修改相关文件夹权限组
chown -R root:root /var/lib/jenkins
chown -R root:root /var/cache/jenkins
chown -R root:root /var/log/jenkins
# 重启jenkins
service jenkins restart
运行pipeline
重新构建,jenkins无报错,查看git仓库,执行成功
Running success
到此为止,整个pipeline已经work,你可以很轻松的尝试一键发布小程序
尤其是有多个小程序项目的时候,可以单独建个分组,方便集中管理,再也不需要手动切入不同的仓库,甚至使用小程序开发者工具去打开各个小程序,大概如下
项目集中管理不香么?
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报权限不足
修改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 "系统管理 -> 插件管理 -> 高级",选择下载的文件上传即可
大佬这边是直接把代码打包编译好了?
构建的时候 会把 ci也构建上去导致包很大
我要是想在打包之后生成小程序的二位码改怎么操作,我看了下miniprogram-cli
提供了qrcodeOutputDest,但是这边不知道具体结合jenkines怎么来操作