• Webhooks -比Jenkins更适合小项目的自动化部署工具
  • 发布于 8小时前
  • 6 热度
    0 评论
本文介绍用 Webhooks 代替 Jenkins 更简单地实现自动化部署。不论用 Jenkins 还是 Webhooks,都需要一定的服务端基础。Webhooks 的使用更简单,自然功能就不如 Jenkins 丰富,因此更适合小项目。

背景
笔者一直在小厂子做小项目,只做前端的时候,部署项目就是  npm run build  然后压缩发给后端。后来到另一个小厂子做全栈,开始自己部署,想着捣鼓一下自动化部署。Jenkins 是最流行的自动化部署工具,但是弄到一半我头都大了。我只是想部署一个小项目而已,结果安装、配置、启动 Jenkins 这工作量好像比我手动部署还大呢,必须找个更简单的办法才行。果然经过一番捣鼓,发现 Webhooks 又简单又实用,更适合我们小厂子小项目。

原理
首先我们的项目应该都放在 Git 平台上,主流的 Git 平台上都有 Webhooks。它的作用是:在你推送代码、发布版本等操作时,自动向你提供的地址发一个请求。你的服务器收到这个请求后,要做的事情就是调用一段事先写好的脚本。这段脚本的任务是拉取最新代码、安装依赖(可选)、打包项目、重新启动项目。这样当你在 Git 平台上发布版本后,服务器就会自动部署最新代码了。

实现
实现步骤可以和上面的原理反着来:先写好脚本,然后启动服务,最后创建 Webhooks。在此之前,你的服务器需要先安装 Git,并能够拉取你的代码。这部分内容很常规,看官可以在其他地方搜到。

1. 自动部署脚本
Nuxt
自动部署脚本就是代替我们手动打包、部署的工作。在 Linux 中,它应该写在一个 .sh 文件里。我的前端项目用 Nuxt 开发,脚本主要内容如下:
# 进入项目文件
cd /usr/local/example
# 拉取最新代码
git pull
# 打包
npm run build
# 重启服务
pm2 reload ecosystem.config.js
你可以在 Git 上随便更新点内容,然后在 XShell 或其他工具打开服务器控制台,执行这段代码,然后到线上版本看更新有没有生效。笔记一开始经过了一番折腾,发现最好得记录部署日志,那样方便排查问题。完整脚本如下:
# 日志文件路径
LOG_FILE="/usr/local/example/$(date).txt"
# 记录开始时间
echo "Deployment started at $(date)" > $LOG_FILE
# 进入项目文件
cd /usr/local/example
# 拉取最新代码
git pull >> $LOG_FILE 2>&1
# 打包
npm run build >> $LOG_FILE 2>&1
# 重启服务
pm2 reload ecosystem.config.js >> $LOG_FILE 2>&1
# 记录结束时间
echo "Deployment finished at $(date)" >> $LOG_FILE
Eggjs
笔者后端用了 Eggjs,其自动部署脚本如下:
# 堆代码 duidaima.com
# 日志文件
LOG_FILE="/usr/local/example/$(date).txt"
# 记录开始时间
echo "Deployment started at $(date)" > $LOG_FILE
# 进入项目文件
cd /usr/local/example
# 拉取最新代码
git pull >> $LOG_FILE 2>&1
# Egg 没有重启命令,要先 stop 再 start
npm stop >> $LOG_FILE 2>&1
npm start >> $LOG_FILE 2>&1
# 记录结束时间
echo "Deployment finished at $(date)" >> $LOG_FILE
Eggjs 项目没有构建的步骤,其依赖要事先安装好。因此如果开发过程中安装了新依赖,记得到服务端安装一下。

Midwayjs
由于 Eggjs 对 TypeScript 的支持比较差,笔者后来还用了 Midwayjs 来开发服务端,其脚本如下:
# 日志文件
LOG_FILE="/usr/local/example/$(date).txt"

# 记录开始时间
echo "Deployment started at $(date)" > $LOG_FILE

# 进入项目文件
cd /usr/local/example

# 拉取最新代码
git pull >> $LOG_FILE 2>&1
# 重装依赖
export NODE_ENV=development
npm install >> $LOG_FILE 2>&1
# 构建
npm run build >> $LOG_FILE 2>&1
# 移除开发依赖
npm prune --omit=dev >> $LOG_FILE 2>&1
# 启动服务
npm start >> $LOG_FILE 2>&1
# 记录结束时间
echo "Deployment finished at $(date)" >> $LOG_FILE
Midwayjs 的自动部署脚本比较特殊:在  npm install  之前需要先指定环境为  development ,那样才会安装所有依赖,否则会忽略  devDependencies  中的依赖,导致后面的  npm run build  无法执行。这点也是费了笔者好长时间才排查清楚,因为它在 XShell 里执行的时候默认的环境就是  development ,但是到了 Webhooks 调用的时候又变成了  product 。

2. 启动一个独立的小服务
上面这些脚本,应该由一个独立的小服务来执行。笔者一开始让项目的 Eggjs 服务来执行,也就是想让 Eggjs 服务自动部署自己,就失败了。原因是:脚本在执行到  npm stop  时,Eggjs 服务把自己关掉了,自然就执行不了  npm start 。笔者启动了一个新的 Eggjs 服务来实现这个功能,使用其他语言、框架同理。其中执行脚本的控制器代码如下:
const { Controller } = require('egg');
const { exec } = require('child_process');
class EggController extends Controller {
 async index() {
   const { ctx } = this;
   try {
     // 执行 .sh 脚本
     await exec('sh /usr/local/example/egg.sh');
     ctx.body = {
       'msg': 'Deployment successful'
     };
   } catch (error) {
     ctx.body = {
       'msg': 'Deployment failed:' + JSON.stringify(error)
     };
   }
 }
}
module.exports = EggController;
如果启动成功,你应该可以在 Postman 之类的工具上发起这个控制器对应的请求,然后成功执行里面的 .sh 脚本。
注意:这些请求必须是 POST 请求。

3. 到 Git 平台创建 Webhooks
笔者用的是GitCode,其他平台类似。到代码仓库 -> 项目设置 -> WebHook 菜单 -> 新建 Webhook:

URL:上面独立小服务的请求地址; Token:在 Git 平台生成即可; 事件类型:我希望是发布版本的时候触发,所以选  Tag推送事件 。  创建好之后,激活这个 hook,然后随便提交些新东西,到代码仓库 -> 代码 -> 创建发行版:

填写版本号、版本描述后,滑到底部,勾选“最新版本”,点击发布按钮。

这样就能触发前面创建的 WebHook,向你的独立小服务发送请求,小服务就会去调用自动部署脚本。怎么样,是不是比 Jenkins 简单太多了。当然功能也比 Jenkins 简单太多,但是对小厂子小项目来说,也是刚好够用。
用户评论