git webhooks 实现自动拉取代码

一. 关于 git 钩子

Git 能在特定的重要动作发生时触发自定义脚本。 有两组这样的钩子:客户端的和服务器端的。 客户端钩子由诸如提交和合并这样的操作所调用,而服务器端钩子作用于诸如接收被推送的提交这样的联网操作。 你可以随心所欲地运用这些钩子。

  • 如何使用钩子

钩子都被存储在 Git 目录下的 hooks 子目录中。 也即绝大部分项目中的 .git/hooks 。 当你用 git init 初始化一个新版本库时,Git 默认会在这个目录中放置一些示例脚本。这些脚本除了本身可以被调用外,它们还透露了被触发时所传入的参数。 所有的示例都是 shell 脚本,其中一些还混杂了 Perl 代码,不过,任何正确命名的可执行脚本都可以正常使用 —— 你可以用 Ruby 或 Python,或其它语言编写它们。 这些示例的名字都是以 .sample 结尾,如果你想启用它们,得先移除这个后缀。

把一个正确命名且可执行的文件放入 Git 目录下的 hooks 子目录中,即可激活该钩子脚本。 这样一来,它就能被 Git 调用。 接下来,我们会讲解常用的钩子脚本类型。

具体使用可以参考官方文档:Git Hookes

  • 了解 webhooks

钩子功能(callback),是帮助用户 push 了代码后,自动回调一个你设定的 http 地址。 这是一个通用的解决方案,用户可以自己根据不同的需求,来编写自己的脚本程序(比如发邮件,自动部署等);目前,webhooks 支持多种触发方式,支持复选。

webhooks 的请求方式为POST请求,有两种数据格式可以选择,JSON 和 web 的 form参数,可以自行选择是否使用密码来确定请求。(注意:该密码是明文)

不同托管平台的POST数据格式都不太一样,不过也不会有太大影响,只是解析数据的时候注意就行了,下面是码云的 Push 操作回调的 json 数据:

{
    "before": "fb32ef5812dc132ece716a05c50c7531c6dc1b4d", 
    "after": "ac63b9ba95191a1bf79d60bc262851a66c12cda1", 
    "ref": "refs/heads/master", 
    "user_id": 13,
    "user_name": "123", 
    "user": {
      "name": "123",
      "username": "test123",
      "url": "https://gitee.com/oschina"
    }, 
    "repository": {
        "name": "webhook", 
        "url": "http://git.oschina.net/oschina/webhook", 
        "description": "", 
        "homepage": "https://gitee.com/oschina/webhook"
    }, 
    "commits": [
        {
            "id": "ac63b9ba95191a1bf79d60bc262851a66c12cda1", 
            "message": "1234 bug fix", 
            "timestamp": "2016-12-09T17:28:02 08:00", 
            "url": "https://gitee.com/oschina/webhook/commit/ac63b9ba95191a1bf79d60bc262851a66c12cda1", 
            "author": {
                "name": "123", 
                "email": "123@123.com", 
                "time": "2016-12-09T17:28:02 08:00"
            }
        }
    ], 
    "total_commits_count": 1, 
    "commits_more_than_ten": false, 
    "project": {
        "name": "webhook", 
        "path": "webhook", 
        "url": "https://gitee.com/oschina/webhook", 
        "git_ssh_url": "git@gitee.com:oschina/webhook.git", 
        "git_http_url": "https://gitee.com/oschina/webhook.git", 
        "git_svn_url": "svn://gitee.com/oschina/webhook", 
        "namespace": "oschina", 
        "name_with_namespace": "oschina/webhook", 
        "path_with_namespace": "oschina/webhook", 
        "default_branch": "master"
    }, 
    "hook_name": "push_hooks", 
    "password": "pwd"
}
以上参考:https://segmentfault.com/a/1190000012643992

二. 服务器环境

  1. centos 7
  2. jdk 1.8
  3. maven 3+
  4. git
  5. nodejs

三.部署

  • 1.安装git

    yum -y install git
  • 2.安装maven

    maven的景象仓库
    http://mirror.bit.edu.cn/apache/maven/maven-3/3.2.5/binaries/
  1. wget http://mirror.bit.edu.cn/apache/maven/maven-3/3.2.5/binaries/apache-maven-3.2.5-bin.tar.gz
  2. tar -zxvf apache-maven-3.2.5-bin.tar.gz
  3. mv apache-maven-3.2.5 /usr/local/maven3
  4. vim /etc/profile
# JAVA
export JAVA_HOME=/usr/jdk/jdk1.8.0_192
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export  PATH=${JAVA_HOME}/bin:$PATH

#maven
export M2_HOME=/usr/local/maven3
export PATH=$PATH:$JAVA_HOME/bin:$M2_HOME/bin
  1. source /etc/profile
  • 3.配置git ssh拉取代码

  • 生成公钥

    此示例是单机部署,所以不需要生成ssh免密登录公钥

  • 用户公钥(用于git clone时认证权限)

ssh-keygen -t rsa -C "test@qq.com" # 填自己的邮箱

生成公钥的示例 默认保存在 /root/.ssh/id_rsa,可以自己修改位置,此处默认

  • git部署公钥
  1. 获取公钥内容
cat /root/.ssh/id_rsa.pub # 查看生成的密钥内容,复制全部
  1. gitee仓库中添加ssh公钥

将公钥的内容粘贴到用户->设置 中的SSH公钥中
gitee中设置部署公钥

  • git全局设置
 git config --global credential.helper store # 永久保存
 git config --global user.name "name" 
 git config --global user.email "test@qq.com" # 邮箱请与码云上一致
  • 拉取代码
    git clone git@gitee.com:test/test-pull.git #这个是你仓库的ssh地址
    

    如果报错:
    /etc/ssh/ssh_config: line 53: Bad configuration option: permitrootlogin
    /etc/ssh/ssh_config: terminating, 1 bad configuration options
    修改方法为:

    vim /etc/ssh/ssh_config 
    注释掉 permitrootlogin 
    

    配置完成之后可以 clone 或 pull 项目来验证是否配置成功,若多次操作只需输入一次用户名、密码,即配置成功,若每一次操作都有输入用户名密码,则配置不成功,需要重新检查配置。

  • 4、安装nodejs

  • 下载nodejs最新的bin包
wget https://nodejs.org/dist/v10.16.3/node-v10.16.3-linux-x64.tar.xz
  • 解压安装
xz -d node-v10.16.3-linux-x64.tar.xz
tar -xf node-v10.16.3-linux-x64.tar
mv node-v10.16.3-linux-x64 /usr/local/node
  • 配置bin
ln -s /usr/local/node/bin/node /usr/bin/node
ln -s /usr/local/node/bin/npm /usr/bin/npm
  • 验证
node -v
npm

分别输出版本号,标识成功

  • 5.编写自动部署脚本

  • java自动编译、部署脚本
#/bin/bash
#服务路径
SH_PATH='/usr/soft/sh_root'
SOURCE_PATH='/usr/soft/back/game_web'
DEPLOY_PATH='/usr/soft/jar'
JAR_NAME='web-admin.jar'

#单实例逻辑
if [ -f /var/run/${BASH_SOURCE[0]}.pid ];then
    echo "pid文件存在。。需要判断是不是当前正在运行的文件"
	ps -ef|grep -v grep|grep ${BASH_SOURCE[0]}|grep `cat /var/run/${BASH_SOURCE[0]}.pid` >> /dev/null
	if [ $? -eq 0 ];then
		exit 1
	fi
fi
echo "写入临时文件"
echo $$ > /var/run/${BASH_SOURCE[0]}.pid


#停止原本服务
PID=$(jps |grep -v  Jps| awk '{ print $1 }')
echo "原始运行的服务id是:$PID"
if [ -n "$PID" ]
then
  echo "原来服务存在,需要kill"
  kill -9 $PID;
fi

cd $DEPLOY_PATH
rm -rf *
echo "删除原部署目录文件。。。"
#拉取最新代码部署
cd $SOURCE_PATH
git reset --hard origin/master
git clean -f
git pull
git checkout master
echo "拉取代码完成。。。。。"
#也可以 
#rm -rf *
#git clone git@gitee.com:srxxfd/game_web.git
mvn clean -U install -P prod -Dmaven.test.skip=true
echo "编译完成。。。。"
if [ $? -ne 0 ]
then
  echo "构建失败,请查看代码问题!"
  exit 1;
fi

mv target/web-admin-1.0.0.jar $DEPLOY_PATH/$JAR_NAME
cd $DEPLOY_PATH
echo "进入到部署目录。。。"
#如果不行 就使用 setsid
#nohup java -jar $JAR_NAME &
source $SH_PATH/start_jar.sh "$DEPLOY_PATH" "$JAR_NAME"
echo "编译完成。。。。"
if [ $? -ne 0 ]
then
  echo "启动失败。。。"
  exit 1;
fi
echo "启动完成。。。。"
rm -f /var/run/${BASH_SOURCE[0]}.pid
exit 0;

start_jar.sh

   #!/bin/bash
  #获取参数
  DEPLOY_PATH=$1
  JAR_FILE_NAME=$2
  echo "DEPLOY_PATH 是:$DEPLOY_PATH"
  echo "JAR_FILE_NAME 是:$JAR_FILE_NAME"
  cd $DEPLOY_PATH
  echo "进去到jar目录"
  nohup java -jar $JAR_FILE_NAME > nohup.log 2>&1 &
 exit 0

  • 部署前端代码是
#/bin/bash
#服务路径
SOURCE_PATH='/home/soft/code/front'
DEPLOY_PATH='/usr/local/nginx/html/'
echo "服务路径是:$SOURCE_PATH"
#拉取最新代码部署
cd $SOURCE_PATH
git reset --hard origin/master
git clean -f
git pull
git checkout master
echo "拉取代码完成。。。。。"
mv -rf * $DEPLOY_PATH
echo "部署完成。。。。。"

在执行上面shell脚本之前我们必须第一次手动git clone项目进去

  • 6.监听web-hooks服务

  • 引用 gitee-webhook-handler
mkdir /usr/soft/web_hooks #创建目录
cd /usr/soft/web_hooks
npm init 
npm install  gitee-webhook-handler --save 
  • 创建js
vim webhook.js


var http = require('http')
var createHandler = require('gitee-webhook-handler')
var handler = createHandler({ path: '/webhooks_push', secret: '654321'}) //post 所需要用到的秘钥
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) });
}
handler.on('error', function (err) {
  console.error('Error:', err.message)
})
handler.on('Push Hook', function (event) {
 // 这个地方就是GitHub 和 Gitee 不一样的地方,需要注意
  console.log('Received a push event for %s to %s',
    event.payload.repository.name,
    event.payload.ref);
    // 需要执行的脚本位置
    if (name === "back") {
        run_cmd('sh', ['/home/soft/sh_root/deploy_java.sh'], function (text) {
            console.log(text)
        });
    }else if (name === "front") {
        run_cmd('sh', ['/usr/soft/sh_root/deploy_js.sh'], function (text) {
            console.log(text)
        });
    }else {
        console.log("unknow repository name:" + name);
    }
})
try {
  http.createServer(function (req, res) {
    handler(req, res, function (err) {
      res.statusCode = 404
      res.end('no such location')
    })
  }).listen(6666) // 服务监听的端口,可以自行修改
}catch(err){
  console.error('Error:', err.message)
}

  • 启动服务
npm install -g forever #解决node服务自动停掉
ln -s /usr/local/node/lib/node_modules/forever/bin/forever /usr/bin/forever 
forever start -l forever.log -o out.log -e err.log webhook.js
forever start -a  -l /usr/soft/web_hooks/forever.log -o /usr/soft/web_hooks/forever_out.log -e /usr/soft/web_hooks/forever_err.log webhook.js
  • gitee配置

在这里插入图片描述

  • nginx反向代理
location ^~ /webhooks_push {
            proxy_set_header Host $host;
            proxy_set_header X-Real-Ip $remote_addr;
            proxy_set_header X-Forwarded-For $remote_addr;
            proxy_pass http://127.0.0.1:6666;
        }

保存后,如果服务启动没有问题,会返回 {“ok”:true}

至此配置完成,push完代码之后,可以看到调用到了服务器上

======增加gitlab配置

gitlab-webhook-handler

地址:https://www.npmjs.com/package/gitlab-webhook-handler2

var http = require('http')
var createHandler = require('gitlab-webhook-handler')
var handler = createHandler({ path: '/webhooks_push'})
//var handler = createHandler({ path: '/webhooks_push', events: ['Push Hook', 'Issue Hook']})
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)
})

console.log("Gitlab Hook Server running at http://0.0.0.0:7777/webhooks_push");
handler.on('push', function (event) {
  console.log('Received a push event for %s to %s',
    event.payload.repository.name,
    event.payload.ref)
    var repository_name=event.payload.repository.name;
//    if( repository_name == "Pear Admin Boot"  ){
	run_cmd('sh', ['/home/soft/sh_root/deploy.sh'], function(text){ console.log(text) });
  //   }



})

handler.on('Issue Hook', function (event) {
  console.log('Received an issue event for %s action=%s: #%d %s',
    event.payload.user.name,
    event.payload.object_attributes.action,
    event.payload.object_attributes.id,
    event.payload.object_attributes.title)
})

npm i gitlab-webhook-handler2

服务器如果存在多个node环境,使用nvm管理,在shell脚本中切换版本,不生效问题

#/bin/bash
source /root/nvm/nvm.sh
#服务路径
SOURCE_PATH='/home/soft/project_source/zsxq/'
DEPLOY_BASE_PATH='/home/soft/deploy/'
echo "服务路径是:$SOURCE_PATH"
#拉取最新代码部署
cd $SOURCE_PATH
git reset --hard origin/master
git clean -f
git pull
git checkout master
echo "拉取代码完成。。。。。"
echo "node 版本:`node -v`"
nvm use v12.16.1
echo "nvm:`nvm list`"
echo "node 版本:`node -v`"
#普通用户编译
npm run build
rm -rf $DEPLOY_BASE_PATH/topic/*
mv dist/zsxq/* /home/soft/deploy/topic/
echo "普通用户部署完成。。。。。"

#管理用户编译
npm run buildAdmin
rm -rf $DEPLOY_BASE_PATH/adminTopic/*
mv dist/zsxq/* /home/soft/deploy/adminTopic/
echo "admin用户部署完成。。。。。"

source /root/nvm/nvm.sh 用来执行nvm脚本

找nvm.sh 路径:find / -name “nvm.sh”

参考内容

  1. https://aotu.io/notes/2016/01/07/auto-deploy-website-by-webhooks-of-github/index.html
  2. https://segmentfault.com/a/1190000003908244
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值