8ctopus / git-hook

自动化GitHub和Gitea的git推送部署

3.0.1 2024-03-07 07:25 UTC

This package is auto-updated.

Last update: 2024-08-26 14:41:18 UTC


README

packagist downloads min php version license tests code coverage badge lines of code

使用webhooks自动化GitHub和Gitea的git推送部署。

自动将git仓库更改推送到任何网站。

演示

  • 克隆仓库
  • 启动本地PHP开发服务器:php -S localhost:80 demo.php
  • 运行curl请求以模拟webhook请求
curl \
    --request POST \
    --header "content-type: application/json" \
    --header "X-HUB-SIGNATURE-256: 2d8e4a6f3114e41f09a65195b2d69b5844e7a1a9284cdb2671354568304dd7a6" \
    --data '{"ref":"refs/heads/master", "before":"fc7fc95de2d998e0b41e17cfc3442836bbf1c7c9", "after": "fc7fc95de2d998e0b41e17cfc3442836bbf1c7c9", "total_commits":1, "repository":{"name": "site"}}' \
    http://localhost/

安装

composer require 8ctopus/git-hook

GitHub使用方法

  • 在网站公开部分创建一个新页面,例如这个页面(在这个例子中 https://example.com/api/myhook/index.php
use Apix\Log\Logger\File;
use HttpSoft\ServerRequest\ServerRequestCreator;
use Oct8pus\GitHubHook;

// assuming script is in DOCUMENT_ROOT/public/api/myhook/index.php
$documentRoot = __DIR__ . '/../../..';

require_once $documentRoot . '/vendor/autoload.php';

$commands = [
    // repository name eg. https://github.com/8ctopus/site
    'site' => [
        // directory in which commands will be executed
        'path' => $documentRoot,
        'commands' => [
            // adjust to your flavor
            '/usr/bin/git pull',
            '/usr/local/bin/composer install --no-interaction --no-dev',
        ],
    ],
];

// the logger is optional but provides useful information (any PSR-3 logger will do)
// to use this logger, composer require 8ctopus/apix-log
$logger = new File(sys_get_temp_dir() . '/git-hook-' . date('Y-m-d-His') . '.log');

try {
    $logger->info('Git hook...');

    $request = ServerRequestCreator::createFromGlobals($_SERVER, $_FILES, $_COOKIE, $_GET, $_POST);

    (new GitHubHook($request, $commands, 'SAME_SECRET_KEY_AS_IN_GITHUB_ADMIN', $logger))
        ->run();

    $logger->notice('Git hook - OK');
} catch (Exception $exception) {
    if ($exception->getCode() !== 0) {
        // informs the webhook that the command failed
        http_response_code($exception->getCode());

        // REMOVE ME IN PRODUCTION
        echo $exception->getMessage();
    }
}
  • 在GitHub项目中,转到 设置 > Webhooks > 添加webhook
  • Payload URL 设置为 https://example.com/api/myhook/
  • Content type 设置为 application/json
  • 使用强密码设置 Secret(与脚本中的 SAME_SECRET_KEY_AS_IN_GITHUB_ADMIN 相同)
  • 设置 Just the push event
  • 勾选 Active
  • 点击 添加Webhook
  • 一旦添加,点击它并滚动到最底部以检查第一次投递。如果第一次投递成功,则设置完成。如果失败,请检查响应错误,并在修复后点击 重发

注意:请参阅下面的重要说明。

Gitea使用方法

  • 在网站公开部分创建一个新页面,例如这个页面(在这个例子中 https://example.com/api/myhook/index.php
declare(strict_types=1);

use Apix\Log\Logger\File;
use HttpSoft\ServerRequest\ServerRequestCreator;
use Oct8pus\GiteaHook;

// assuming script is in DOCUMENT_ROOT/public/api/myhook/index.php
$documentRoot = __DIR__ . '/../../..';

require_once $documentRoot . '/vendor/autoload.php';

$commands = [
    'site' => [
        'path' => $documentRoot,
        'commands' => [
            // adjust to your flavor
            '/usr/bin/git pull',
            '/usr/local/bin/composer install --no-interaction --no-dev',
        ],
    ],
];

// the logger is optional but provides useful information (any PSR-3 logger will do)
// to use this logger, composer require 8ctopus/apix-log
$logger = new File(sys_get_temp_dir() . '/git-hook-' . date('Y-m-d-His') . '.log');

try {
    $logger->info('Git hook...');

    $request = ServerRequestCreator::createFromGlobals($_SERVER, $_FILES, $_COOKIE, $_GET, $_POST);

    (new GiteaHook($request, $commands, 'SAME_SECRET_KEY_AS_IN_GITEA_ADMIN', $logger))
        ->run();

    $logger->notice('Git hook - OK');
} catch (Exception $exception) {
    if ($exception->getCode() !== 0) {
        // informs the webhook that the command failed
        http_response_code($exception->getCode());

        // REMOVE ME IN PRODUCTION
        echo $exception->getMessage();
    }
}
  • 更新您的Gitea配置,以便允许将webhooks发送到您的域
[webhook]
SKIP_TLS_VERIFY = false
ALLOWED_HOST_LIST = example.com
  • 在Gitea项目中,转到 设置,从 添加webhook 中选择 Gitea
  • Target URL 设置为 https://example.com/api/myhook/
  • HTTP Method 设置为 POST
  • Post Content Type 设置为 application/json
  • 使用强密码设置 Secret(与脚本中的 SAME_SECRET_KEY_AS_IN_GITEA_ADMIN 相同)
  • Trigger On 设置为 Push Events
  • Branch filter 设置为 master 或您想要触发脚本的任何分支
  • 勾选 Active
  • 点击 添加Webhook
  • 一旦添加,点击它并滚动到最底部并点击 测试投递
  • 如果投递成功,则设置完成。如果失败,请转到服务器并检查日志。

GitHub和Gitea的重要说明

注意:为了使使用用户 www-data(Apache通常运行在该用户下)的git pull工作,您可能需要

  • 确保已设置上游,以便git知道从哪里拉取
git branch --set-upstream-to=origin/master master
  • 确保用户 www-data 是git仓库的所有者。如果不是,您将收到错误消息
[2023-05-05 16:23:21] ERROR fatal: detected dubious ownership in repository at '...'

注意:如果您对安全性较弱,您可以考虑授予用户 www-data 运行git作为另一个用户(如 ubuntu)的权限。这样,您的web服务器文件可以由 ubuntu 拥有,而 www-data 只能读取它们。我不是安全专家,所以请小心。

sudo -H -u ubuntu -- /usr/bin/git pull;

注意:为了使使用用户 www-data(Apache进程通常运行在该用户下)的git pull工作,您可能需要

- 在git remote url中包含用户和密码(必须进行url编码)

- git remote set-url origin https://user:password@example.com/gitea/site.git

回调

可以为每个命令或所有命令实现回调

$commands = [
    'site' => [
        'path' => $path,
        'commands' => [
            'git status' => commandCallback(...),
            'composer install --no-interaction',
        ],
        'afterExec' => globalCallback(...),
    ],
];

这两个回调具有相同的签名

function callback(?LoggerInterface $logger, string $command, string $stdout, string $stderr, string $status) : bool

返回false将终止部署

调试

可以使用ngrok轻松地在本地调试部署脚本。

  • 运行ngrok ngrok http 80
  • 将 Github 的 Payload URL 或 Gitea 的 Target URL 更新为 ngrok 地址,类似于这个 https://6daf-31-218-13-51.ngrok-free.app
  • 运行 PHP 本地服务器 php -S localhost:80 demo.php
  • 启动 Visual Studio Code 调试并设置 demo.php 的断点
  • 重新发送 webhook 请求

清理代码

composer fix(-risky)

phpstan

composer phpstan

phpmd

composer phpmd