用GitHub的Webhooks打造前端自动化构建部署

2,548 阅读5分钟

前言

随着前端工程化的推进,现在的前端开发流程已经日趋规范化,在我们的日常开发中,每完成一次功能的开发,一般需要经过以下步骤:

  1. Git提交代码
  2. Webpack打包源码
  3. 上传服务器
  4. 重启服务器上部署的服务(例如Nginx)

如果这些步骤每一次都需要手动执行,难免显得繁琐、效率低下,作为一个程序员,怎么能忍受?如果能做到我们一提交代码,自动的帮我们打包构建=>部署=>重启服务就省事多了。之前一直有了解到GitHub有Webhooks这个功能,这篇记录就来填个坑,实现前端工程的自动化部署。

1 准备工作

1.1 项目初始化

出于示例目的,先在Github中开一个新的仓库命名为Webhooks-demo,使用vue-cli生产初始代码,并上传到仓库中,并把项目部署到服务器(本文使用腾讯云,操作系统为ubuntu)运行。

1.2 项目运行环境搭建

本文项目服务器环境使用nginx作为代理服务器运行,需要在nginx配置中设置目录指向项目的dist目录(也就是打包出来的目录)。

location / {
    root /home/ubuntu/webhooks-demo/dist; #网站主页路径。此路径仅供参考,具体按照实际目录操作。
    index  index.html index.htm;
}

使用浏览器访问服务器域名或者公网IP地址,能正常访问则项目运行环境搭建完成

项目运行

2 编写自动化脚本

首先分析实现自动化部署功能的需求:

  1. 当项目仓库发生git push操作时,需要执行git pull操作拉取最新代码
  2. 运行npm install,项目可能会有新加的npm包
  3. 运行npm run build(参考使用,以具体项目为主),使用Webpack打包源码,生成dist目录
  4. 运行sudo service nginx restart,重启nginx服务

2.1 搭建Node服务器

搭建Node服务器,用于监听Webhooks发出的POST请求,并做出下一步操作。

在项目根目录下新建autoBulid.js文件,代码比较简单

const http = require('http')
const createHandler = require('github-webhook-handler')
const handler = createHandler({ path: '/webhook', secret: 'myhashsecret' })
// 上面的 secret 保持和 GitHub Webhooks 后台设置的一致 下文会提到
// secret: 'myhashsecret' 记住 后面会用到
// path 是webhook访问的url 后面会提到

http.createServer(function (req, res) {
  handler(req, res, function (err) {
    res.statusCode = 404
    res.end('no such location')
  })
}).listen(7777)
 
handler.on('error', function (err) {
  console.error('Error:', err.message)
})
 
handler.on('push', function (event) {
  console.log('Received a push event for %s to %s',
    event.payload.repository.name,
    event.payload.ref)
})

这里用到了github-webhook-handler这个包,用于监听Webhooks发出的请求,具体介绍可前往npm查看,此时Node服务基本搭建完成,在服务器中运行autoBulid.js

node autoBulid.js

2.2 Webhooks设置

首先在项目的GitHub主页设置中开启Webhooks功能

开启Webhooks
接下来就是创建Webhooks,在Webhooks的页面我们可以看到一段简短的介绍:

Webhooks allow external services to be notified when certain events happen. When the specified events happen, we’ll send a POST request to each of the URLs you provide.

大概意思就是Webhooks在检测到仓库有事件触发时会发送一个POST请求到你给定的URL去,从而进行后续的部署工作。点击“Add webhook”按钮,创建一个webhook。

新增webhook
创建完成后wenhook会马上模拟发送一个请求用于测试是否请求成功。(这里图中URL漏写/webhook了)
创建成功
如图,看到一个绿色的√,说明webhook创建成功并能正常运行。

2.3 编写.sh脚本

到这一步,项目已经能检测到项目仓库的变更,接下来需要编写脚本来跑命令,实现项目的更新和部署。

同样在根目录下新建一个autoBuild.sh文件,写入以下代码。

git pull origin master      # 拉取最新代码
npm install                 # 安装依赖
npm run build               # 打包
sudo service nginx restart  # 重启nginx

有了脚本文件,我们需要在前面创建的Node服务中调用它,修改autoBuild.js代码。

const http = require('http')
const createHandler = require('github-webhook-handler')
const handler = createHandler({ path: '/webhook', secret: 'myhashsecret' })

http.createServer(function (req, res) {
  handler(req, res, function (err) {
    res.statusCode = 404
    res.end('no such location')
  })
}).listen(7777)
 
handler.on('error', function (err) {
  console.error('Error:', err.message)
})
 
handler.on('push', function (event) {
  console.log('Received a push event for %s to %s',
    event.payload.repository.name,
    event.payload.ref)
    run_cmd('sh', ['./autoBuild.sh'], function(text){ console.log(text) }); // 执行autoBuild.sh
})

// 新增run_cmd函数
function run_cmd(cmd, args, callback) {
    var spawn = require('child_process').spawn;
    var child = spawn(cmd, args);
    var resp = "";

    child.stdout.on('data', function(buffer) { resp += buffer.toString(); });
    child.stdout.on('end', function() { callback (resp) });
}

执行git push提交代码,服务器上拉取代码并运行node autoBuild.js

接下来我们在本地修改一下项目的代码,然后提交到Github,测试脚本是否能正常运行。

// App.vue
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
-    <HelloWorld msg="Welcome to Your Vue.js App"/>
+    <HelloWorld msg="Webhook test"/>
  </div>
</template>

本地执行git push提交代码更新到仓库中,通过Xshell观察服务器的输出。

服务器
可以看到,服务器已经检测到项目仓库变化,并自动执行了autoBuild.sh脚本,此时打开浏览器刷新查看页面变化。

页面更新
可以看到,页面已经按照我们修改的代码自动更新了。以后每一次的提交代码,服务器都会帮我们更新代码和打包部署,再也不用自己手动操作啦。

3 总结

到这里,使用Github提供的Webhooks来实现自动化部署就已经大致完成了,整体过程没什么难度,一些细节的地方还可以继续优化,其实能实现的不止有这么多,可以在autoBuild.sh文件中加入单元测试之类,可以发挥的空间还很大。当然,实现自动化部署的方案不止Webhook这一种,现在我所在公司使用的是GitLab的CI,可以使用还有Travis CI和Jenkins等等。这次的记录就写到这里,今年刚毕业萌新第一次在掘金发文章,写的不好的地方望大家谅解。