Git 使用webhooks自动部署

如果你看过我之前的文章《[Linux 搭建svn服务器](/linux-svn-deployment/)》,而且有很巧的看到了最后,那么你应该还记得svn下通过...

如果你看过我之前的文章《Linux 搭建svn服务器》,而且有很巧的看到了最后,那么你应该还记得svn下通过post-commit的钩子实现本地提交服务器上代码实时更新的功能。那么这一次我们来讲下相同的功能如何在git下实现。

那么现在的情况是这样,咱们有一个开源项目托管在github上,部署在自己的服务器上,开发在本地环境,需求是本地提交修改服务器上自动更新代码并部署。实际上github提供了一个叫做webhooks的配置,它的实际原理是github会监听你项目的所有事件(或者只是push事件),当监听到事件发生的时候会去以post方式请求一个接口,这个接口就是你服务器需要提供的,在接口中你就可以做自己的事了。具体操作我们结合实例一步步来看。

github添加hook配置

首先进入我们github项目的设置选项,选择webhooks,然后添加一个webhook。

这里的payload url就是你接口的地址,secret是一个密码,后面会用到。

服务器监本

在服务器端,我们首先写一个脚本deploy.sh,脚本里包含了git的更新操作以及服务器上项目的部署操作。

#!/bin/bash
# deploy.sh

WEB_PATH='My web path'

echo "Start deployment"
cd $WEB_PATH
echo "pulling source code..."
git pull
# 部署操作
echo "Finished."

这里的脚本比较简单,WEB_PATH里就是我们项目的根目录。

服务器接口

然后我们来写接口,这里我们使用node来提供接口,npm有个github-webhook-handler包可以很方便使用,我们创建一个deploy.js文件。我们这个接口的主要作用是监听push事件,在监听事件中去执行我们的deploy.sh脚本。

var http = require('http')
var createHandler = require('github-webhook-handler')
var handler = createHandler({ path: 'My Path', secret: 'My Secret' })
// 上面的 secret 保持和 GitHub 后台设置的一致

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) });
}

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', ['./deploy.sh'], function(text){ console.log(text) });
})

github-webhook-handler需要提供pathsecret字段,这两个都是之前github上设置的。secret不多说了,path的话是你之前填写的地址的路径,比如github设置的地址是http://test.com/post-receive,你的path字段的值就是/post-receive
往下看看到有个run_cmd方法,这个方法就是用来指定deploy.sh的,然后接下去我么你创建了一个服务器,绑定在了7777端口,并且监听了2个事件error和push,在push事件中调用了run_cmd方法。

启动服务

最后我们要把这个js应用部署起来,让它可以被访问。这一块就不怎么细说了,和一般的node应用部署差不多,具体可以看《Linux 部署node项目》。

结尾

完成上述步骤后,当我们下次提交代码到github上后,我们的服务器会自动的更新,自动的部署,这作为一个线上环境的测试服务器来说是比较高效的。