本文以Gitee作为演示,Github实现步骤是一样的,区别在于二者WebHook推送的数据有所区别。

WebHook 1.WebHook是什么 WebHook 功能是帮助用户 push 代码后,自动回调一个您设定的 http 地址。 这是一个通用的解决方案,用户可以自己根据不同的需求,来编写自己的相关程序。

实现过程 1.处理过程

远程仓库接收到Push推送,触发WebHook向接口推送更新的消息; 服务器接口接收到推送的更新消息,提取仓库地址、分支名、仓库名(仓库名用于同步多个仓库时进行区分); 接口将提取的更新信息,投递到后台的异步任务。 异步任务自动执行Git命令,同步指定仓库的代码到对应的目录。

2.功能组成 服务器后台运行一个PHP cli 脚本,脚本运行时启动一个SSH客户端,然后再运行一个Redis客户端,Redis保持订阅,接收来自接口的Redis消息发布。

每当Redis接收到发布的推送消息,触发回调,通过SSH客户端执行Git命令。

实际代码 1.HTTP接口 HTTP接口接收来自远程仓库的更新推送,然后把数据进行处理后推送给异步任务。

<?php /*

  • 创建redis
  • / function getRedis():Redis { \(redis = new Redis(); \)redis->connect(“IP”,“端口”); \(redis->setOption(3, -1); return \)redis; } / 获取推送的数据 / \(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; / 封装一下 */ class Ssh extends SSH2 { private $finish = “@EXEC@”; //结束的标志

private $count = 1; //计算命令条数

public function __construct(\(host, \)port)

{
    parent::__construct($host, $port);
}

/*

 * 获取当前命令的结束标志
 * */
private function getEnd()
{
    return $this->finish . "-" . $this->count;
}

/*

 * 读取消息
 * */
public function read_raw()
{

$raw = “”; //缓存消息 /*

     * 循环读取
     * */
    while (true) {

\(msg = \)this->read(‘username@username:~\('); if (!empty(\)msg)) {

            $raw .= $msg;
        }

/* 结束的标记 */

        if (strpos($raw, $this->getEnd()) !== false) {
            break;
        }
    }

/* 登录 */

    $raw = str_replace($this->getEnd(), "", $raw);
    return str_replace("&& echo", "", $raw);
}

/*

 * 执行命令并输出消息
 */
public function exec_command($command)
{
    $this->write($command . ' && echo ' . $this->getEnd() . "n");
    echo $this->read_raw(); //读取初始化的消息
    $this->count++; //计数++
}

} /*

  • 创建redis
  • / function getRedis():Redis { \(redis = new Redis(); \)redis->connect(“IP”,“端口”); \(redis->setOption(3, -1); return \)redis; } / 结束的标志 / \(redis = getRedis(); //创建redis \)root = “/home/repos/”; //存放仓库的目录 /
  • SSH连接配置
  • */ \(ssh = new Ssh('localhost', 22); /*如果登录失败*/ if (!\)ssh->login(’root‘, ’************‘)) { exit(); } sleep(1); //等待登录,防止write过快导致异常 /设置读取间隔时间/ $ssh->setTimeout(0.1); /*
  • redis订阅消息
  • / \(redis->subscribe(["RECV_GIT"], function (\)redis, \(chan, \)msg) use (\(ssh, \)root) { echo “收到消息:” . \(msg . "n"; //收到消息 if (strpos(\)msg, “branch”) === false) return; try { \(data = json_decode(\)msg, true); //处理结果 / * 判断仓库是否存在 * / \(path = \)root . $data[’path‘]; //本地仓库路径 / * 仓库目录是否存在 * 不存在则创建目录 * */ if (file_exists(\(path)) { \)ssh->exec_command(“rm -rf ” . \(path); //创建目录 } \)ssh->exec_command(“mkdir ” . \(path); //创建目录 \)ssh->exec_command(“cd ” . \(root); //打开所在目录 \)ssh->exec_command(“git clone ” . \(data['clone']); //添加仓库 echo "同步完毕n"; } catch (Throwable \)e) { echo $e->getMessage() . “n”; } }); 3.运行脚本 打开上方Cli脚本所在目录,运行如下命令:

前台运行

php 文件名.php

后台台运行

nohup php 文件名.php &

每次脚本运行的日志,会自动写入到当前目录的nohup.out文件,作为日志方便观察同步结果 ;

运行之后,每次仓库有更新,脚本都会自动同步这一次的更新;本文只是简单的实现,您完全可以通过这个案例实现更复杂的功能。

4.使用秘钥 <?php use phpseclib3\Net\SSH2; use phpseclib3\Crypt\PublicKeyLoader; \(key = PublicKeyLoader::load(file_get_contents("./include/ssh.pem")); \)ssh = new SSH2(’localhost‘,22); \(ssh->login('root', \)key));

5.解决异常的不知名报错

重新启动网络服务器 使用多个并行终端。有时关闭其中一个或两个窗口会有所帮助。 使用 API 为 ssh 用户创建临时并行工作密码。也许我们“有时”登录太快了。创建并行密码后,在登录之前等待 1 秒。

阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。 用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。