怎样编写github或gitee的代码自动部署钩子

项目地址:

一、什么是自动部署钩子?

简单地说自动部署钩子就是实现代码同步的一个程序,程序会在特定的情况会被触发,比如开发者将代码推送到git服务器时。本文使用PHP语言来编写一个能实现PHP项目自动部署的程序。

二、目标需求

本文使用的是码云作为示例,在我们的业务服务器上部署钩子程序,当我们推送代码到码云仓库之后,使码云触发网络钩子功能,实现代码同步到业务服务器,达到项目自动部署的目的。首先需要实现代码同步功能即可,同时,代码同步到业务服务器之后,发送通知邮件给代码推送者。

三、实现过程

1.初始化项目

创建一个空的项目目录,在目录之下使用composer安装一个phpmailer邮件发送依赖库,composer指令如下:

composer require phpmailer/phpmailer

2.定义邮件发送者对象

在项目根目录创建MailSender.php文件,首先在头部引入在1中安装的phpmailer依赖,如下:

<?php
require_once 'vendor/autoload.php';

// 引入phpmailer依赖
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;

在MailSender.php文件中添加MailSender类,并设置SMTP邮件发送的相关参数,如下代码:

class MailSender
{
    /*
     * SMTP配置
     * */
    private $smtp_host = 'smtp.exmail.qq.com';//SMTP服务器地址
    private $smtp_from = '极客开发者-管理员';//发送者
    private $smtp_username = 'admin@jkdev.cn';//邮箱账号
    private $smtp_password = '******';//邮箱密码
    private $smtp_port = '465';//端口号
}

再创建是实例化邮件发送者的方法obtainEmailSender,第一个参数是邮件发送的目标邮箱数组(也就是说,可以同时将通知邮件发到多个目标邮箱),第二个参数代表发送主题,第三代表邮件内容,如下代码:

public function obtainEmailSender(array $addresses, $subject, $body)
    {
        $mailSender = new PHPMailer(true);
        $mailSender->CharSet = 'UTF-8';

        //Server settings
        $mailSender->SMTPDebug = SMTP::DEBUG_SERVER;                       // Enable verbose debug output
        $mailSender->isSMTP();                                             // Send using SMTP
        $mailSender->Host = $this->smtp_host;                              // Set the SMTP server to send through
        $mailSender->SMTPAuth = true;                                      // Enable SMTP authentication
        $mailSender->Username = $this->smtp_username;                      // SMTP username
        $mailSender->Password = $this->smtp_password;                      // SMTP password
        $mailSender->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;             // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` also accepted
        $mailSender->Port = $this->smtp_port;                              // TCP port to connect to

        //Recipients
        $mailSender->setFrom($this->smtp_username, $this->smtp_from);
        foreach ($addresses as $index => $address) {
            $mailSender->addAddress($address);                             // Name is optional
        }

        // Content
        $mailSender->isHTML(true);                                  // Set email format to HTML
        $mailSender->Subject = $subject;
        $mailSender->Body = $body;

        //返回邮件对象
        return $mailSender;
    }

3.定义钩子

创建钩子入口文件index.php,并引入MailSender.php文件,如下代码:

<?php
include 'MailSender.php';

首先验证提交者是否将代码提交到master分支,其次验证密码是否正确。如果验证不通过时,直接退出程序,如下代码:

// 检测IP
if (!in_array($_SERVER['REMOTE_ADDR'], $allowIpArr)) {
    echo '非法IP:' . $_SERVER['REMOTE_ADDR'];
    exit(0);
}

// 获取请求参数
$headers = getallheaders();
$body = json_decode(file_get_contents("php://input"), true);
// 请求密码
$password = 'www.jkdev.cn';

// 验证提交分支是否为master
if (!isset($body['ref']) || $body['ref'] !== 'refs/heads/master') {
    echo '非主分支' . $body;
    exit(0);
}

// 验证提交密码是否正确
if (!isset($body['password']) || $body['password'] !== $password) {
    echo '密码错误';
    exit(0);
}

通过验证之后,在服务器拉取git服务器上的最新代码

// 验证成功,拉取代码
$path = $body['project']['path'];
$command = 'cd /var/www/html/' . $path . ' && git pull 2>&1';
$res = shell_exec($command);

在以上代码中,先使用cd命令进入服务器上的项目目录,这里要注意,项目后缀路径必须和git服务器上的项目路径是一致的。再使用git pull命令拉取代码,使用2>&1指令会返回git执行结果。最后使用shell_exec执行命令并使用$res变量来接收执行结果。
最后,定义通知邮件发送内容,代码如下:

// 发送邮件
$addresses = [
    $body['sender']['email'],// 将邮件发送给发送者
    $body['repository']['owner']['email']// 将邮件发送给仓库所有者
];
// 去除重复的内容
$addresses = array_unique($addresses);

try {
    // 更新说明
    $title = '部署成功通知';
    // 构造邮件内容
    $message = $body['head_commit']['message'];// 提交信息
    $datetime = date('Y-m-d H:i:s', $body['timestamp'] / 1000);// 时间
    $pusher = $body['pusher']['name'];// 提交人
    $name = $body['project']['name'];// 项目名
    $path = $body['project']['path'];// 路径
    $content = <<<HTML
<html>
<body>
    <h2>{$body['project']['name']}已部署成功</h2>
    <p>
    描述:<span style="font-size: 16px; color: cadetblue">$message</span> <br>
    时间:<span style="font-size: 16px; color: red">$datetime</span> <br>
    提交人:<span style="font-size: 16px; color: cadetblue">$pusher</span> <br>
    项目名称:<span style="font-size: 16px; color: cadetblue">$name</span> <br> 
    项目路径:<span style="font-size: 16px; color: cadetblue">$path</span>
    </p>
</body>
</html>
HTML;

    // 发送邮件
    $emailSender = (new MailSender())->obtainEmailSender($addresses, $title, $content);
    $emailSender->send();
    // 返回结果
    echo '邮件发送成功,git pull执行结果:' . $res;
} catch (\PHPMailer\PHPMailer\Exception $e) {
    echo '邮件发送失败,git pull执行结果:' . $res . ',邮件日志:' . $e;
}

在以上代码中,我们使用代码推送者和仓库所有者作为目标邮件通知对象。如果两个目标是同一个邮箱,将只取一个。其次构造邮件发送内容,使用邮件发送者的send方法进行邮件发送。最终,将git拉取结果和邮件发送结果响应给请求者。

四、总结

本文结合码云的网络钩子功能,使用PHP代码编写了一个HTTP接口,当开发者往码云上提交代码时,将触发钩子携带相关信息去调用业务服务器接口,从而我们可以在业务服务器上触发shell命令去同步git服务器上的代码,达到自动部署的目的。你还可以参考码云网络钩子的文档,进而进行代码改进,实现其他的网络钩子相关的业务需求!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268