/ php

Webhooks 实现自动化部署

尴尬

卧艹猛然发现我都大三了,尴尬,先水一波

由于代码直接托管在 GitHub 上,所以在部署站点时不免会有点尴尬:

  • 产品 -v 1.0.0 ,上传到 GitHub git push
  • 进入服务器的相应文件夹中 git pull
  • 啊,有 bug 赶紧修复好 git push
  • 恩好吧到服务器中拉取最新代码 git pull
  • 产品更新 -v 1.2.0 git push
  • ...git pull
  • ......

代码一有改动就必须手动在服务器拉取最新代码,简直了。。。

至于为啥不用 ftp谁用谁知道

Webhooks 解放双手

GitHub 官方的解释:

Webhooks allow external services to be notified when certain events happen within your repository. When the specified events happen, we’ll send a POST request to each of the URLs you provide.

大致意思就是说:你在 GitHub 仓库中一有改动,他们就会自动向你的服务器发送一个 POST 请求,前提是订阅的相关事件,比如 push,更多请转Webhooks Guide.

有了这些就好办事多了,我们只需要在服务器中写一个自动化脚本,在接收 POST 请求后自动执行脚本。

PHP 环境下的一次实践

以下主要记录三点:

  • 自动化 shell 脚本
  • 服务端接收处理 POST 请求的 .php 文件
  • 配置 GitHub 的 Webhooks

首先,创建你的站点根目录并赋予 www-data 对该目录的所有权限 sudo chown -R www-data:www-data 目录名称

Note: 不一定是 www-data,视个人情况而定

然后以下操作均在该目录下进行

自动化 shell 脚本

直接上代码:

#!/bin/bash

# webPath 填写你的站点根目录
webPath="/usr/share/nginx/html/webhook"
# repositoryURL 填写你的仓库地址
repositoryURL="https://github.com/huangxutao/webhook.git"
# repositoryName 填写你的仓库名称
repositoryName="webhook"

# 进入站点根目录
cd $webPath

# 判断是否存在仓库目录, 没有则 clone ,有则 pull
if [ ! -d $repositoryName ]
then
  git clone $repositoryURL
else
  cd $repositoryName && git pull
fi

保存为 deploy.sh 然后赋予它可执行的权限 sudo chmod +x deploy.sh

服务器端实现

直接上代码 :

<?php
  /***
   * 定义 TOKEN 为你在 GitHub 上的设置的 Secret 值
   * 定义 shellPath 为你的自动化部署的 shell 脚本(deploy.sh) 的绝对路径
   */
  define("TOKEN", "thisismysecretvalue");
  define("shellPath", "/usr/share/nginx/html/webhook/deploy.sh");

  /***
   * 当发生 push 事件时的处理函数
   */
  function onPush() {
    // 获取原始数据
    $payload = file_get_contents("php://input");
    $req_signature = $_SERVER["HTTP_X_HUB_SIGNATURE"];
    $my_signature = "sha1=" . hash_hmac('sha1', $payload, TOKEN);

    if(strcmp($req_signature, $my_signature) == 0) {
      system(shellPath, $status);
      echo $status == "true" ? "ok" : "fail";
    } else {
      echo "Signatures didn't match!";
    }
  }

  // 事件类型 push 时执行
  $_SERVER["HTTP_X_GITHUB_EVENT"] == "push" ? onPush() : http_response_code(200);

?>

保存为 sync.php

配置 GitHub 的 Webhooks

见图点击 Add webhooks, 给当前仓库添加 webhooks

enter image description here

然后填写相应的数据

  • Payload URL 为响应 GitHub 请求的地址
  • Content type 默认为 json 格式
  • Secret 随意填,在上面的 sync.php 中定义 TOKEN时会用到;当然也可以不填,自然也就不怎么安全

enter image description here

点击添加 Webhooks 后,GitHub 会发送一个 X-GitHub-Eventping 的测试请求

看见小绿钩了吗,说明配置成功了:

enter image description here

写在最后

原文地址

没错又是一篇软文,但还是学到了些

总结下:

了解了基本的 shell 语法

学习了 php 关于 json 的处理函数

// 获取 post 请求的 json 数据
file_get_contents("php://input");

// 用于 json 编码
json_encode();

// 用于 json 解码
json_decode();

// 用 HMAC 模式生成一个包含密钥的哈希码。
hash_hmac(string $algo , string $data , string $key);

参考文档