原文:
https://nicen.cn/3368.html
本文以Gitee作为演示,Github实现步骤是一样的,区别在于二者WebHook推送的数据有所区别。
WebHook
1.WebHook是什么
WebHook 功能是帮助用户 push 代码后,自动回调一个您设定的 http 地址。 这是一个通用的解决方案,用户可以自己根据不同的需求,来编写自己的相关程序。
实现过程
1.处理过程
- 远程仓库接收到Push推送,触发WebHook向接口推送更新的消息;
- 服务器接口接收到推送的更新消息,提取仓库地址、分支名、仓库名(仓库名用于同步多个仓库时进行区分);
- 接口将提取的更新信息,投递到后台的异步任务。
- 异步任务自动执行Git命令,同步指定仓库的代码到对应的目录。
2.功能组成
服务器后台运行一个PHP cli 脚本,脚本运行时启动一个SSH客户端,然后再运行一个Redis客户端,Redis保持订阅,接收来自接口的Redis消息发布。
每当Redis接收到发布的推送消息,触发回调,通过SSH客户端执行Git命令。
PHP SSH 客户端
实际代码
1.HTTP接口
HTTP接口接收来自远程仓库的更新推送,然后把数据进行处理后推送给异步任务。
<?php
/* 获取推送的数据 */
$json = file_get_contents("php://input");
$data = json_decode($json, true);
/* 判断推送是否来自指定的用户 */
if ($data['user_name'] != "friend-nicen") {
exit("非法请求");
}
/* 处理数据 */
$need = [
"clone" => $data['repository']["clone_url"], //远程仓库地址
"path" => $data['repository']["path"], //远程仓库名
"branch" => str_replace("refs/heads/", '', $data['ref']) //分支
];
/*通过Redis订阅,进行任务投递*/
getRedis()->publish("RECV_GIT", json_encode($need));
exit("正在处理本次更新...");
2.PHP Cli脚本
使用前请先按照
https://nicen.cn/2430.html
,安装PHP拓展,您需要准备:
- Redis的IP和端口
- SSH账号和密码
- 存放所有仓库的根目录
<?php
include_once 'vendor/autoload.php';
/* 引入SSH客户端 */
use phpseclib3\Net\SSH2;
/*
* 创建redis
* */
function getRedis():Redis
{
$redis = new Redis();
$redis->connect("IP","端口");
$redis->setOption(3, -1);
return $redis;
}
/*链接ssh*/
$ssh = new SSH2('localhost', 22);
/*如果登录失败*/
if (!$ssh->login('root', '您的SSH密码')) {
return;
}
/*
* SSH读取消息
* */
$read = function () use ($ssh) {
/*拼接*/
$raw = "";
/*读取空白次数*/
$blank = 0;
/*
* 循环读取
* */
while (true) {
$msg = $ssh->read('username@username:~$');
if (!empty($msg)) {
$raw .= $msg;
} else {
/*
* 空白10次,终止,返回
* */
if ($blank > 10) {
break;
} else {
$blank++;
}
}
}
return $raw;
};
/*读取间隔时间*/
$ssh->setTimeout(0.1);
$redis = getRedis(); //创建redis
/*
* 打开存放仓库的目录
* */
$root = "/home/repos/"; //存放仓库的目录
$ssh->write("cd " . $root . "\n");
echo $read(); //读取初始化的消息
/*
* Redis订阅等待消息
* */
$redis->subscribe(["RECV_GIT"], function ($redis, $chan, $msg) use ($ssh, $read, $root) {
echo "收到消息:" . $msg . "\n"; //收到消息
/*
* 判断消息内容是否包含分支信息
* */
if (strpos($msg, "branch") === false) return;
try {
$data = json_decode($msg, true); //处理结果
/*
* 判断仓库是否存在
* */
$path = $root . $data['path']; //本地仓库路径
/*
* 仓库目录是否存在
* */
if (!file_exists($path)) {
/*创建*/
mkdir($path);
/*打开仓库目录*/
$ssh->write("cd " . $path . "\n");
/*初始化仓库*/
$ssh->write("git init\n");
echo $read(); //读取后续的消息
/*添加远程仓库*/
$ssh->write("git remote add origin " . $data['clone'] . "\n");
echo $read(); //读取后续的消息
} else {
/*打开仓库目录*/
$ssh->write("cd " . $path . "\n");
}
/*拉取分支*/
$ssh->write("git pull origin " . $data['branch'] . ":" . $data['branch'] . " \n");
echo $read(); //读取后续的消息
} catch (\Throwable $e) {
echo $e->getMessage() . "\n";
}
});
3.运行脚本
打开上方Cli脚本所在目录,运行如下命令:
# 前台运行
php 文件名.php
# 后台台运行
nohup php 文件名.php &
每次脚本运行的日志,会自动写入到当前目录的nohup.out文件,作为日志方便观察同步结果 ;
运行之后,每次仓库有更新,脚本都会自动同步这一次的更新;本文只是简单的实现,您完全可以通过这个案例实现更复杂的功能。
版权声明:本文为qq_34211600原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。