146 lines
4.4 KiB
PHP
146 lines
4.4 KiB
PHP
<?php
|
|
namespace Misuzu;
|
|
|
|
use Misuzu\DB;
|
|
use Misuzu\Changelog\ChangelogChange;
|
|
|
|
$misuzuBypassLockdown = true;
|
|
require_once '../misuzu.php';
|
|
|
|
function ghcb_strip_prefix(string $line): string {
|
|
$findColon = mb_strpos($line, ':');
|
|
return trim($findColon === false || $findColon >= 10 ? $line : mb_substr($line, $findColon + 1));
|
|
}
|
|
|
|
function ghcb_changelog_action(string &$line): int {
|
|
$original = trim($line);
|
|
$line = ghcb_strip_prefix($line);
|
|
|
|
$firstSix = mb_strtolower(mb_substr($original, 0, 6));
|
|
|
|
if($firstSix === 'revert'
|
|
|| $firstSix === 'restor')
|
|
return ChangelogChange::ACTION_REVERT;
|
|
if($firstSix === 'import')
|
|
return ChangelogChange::ACTION_IMPORT;
|
|
|
|
$firstThree = mb_strtolower(mb_substr($original, 0, 3));
|
|
|
|
if($firstThree === 'add'
|
|
|| $firstSix === 'create')
|
|
return ChangelogChange::ACTION_ADD;
|
|
if($firstThree === 'fix')
|
|
return ChangelogChange::ACTION_FIX;
|
|
|
|
$firstFour = mb_strtolower(mb_substr($original, 0, 4));
|
|
$firstEight = mb_strtolower(mb_substr($original, 0, 8));
|
|
|
|
if($firstSix === 'delete'
|
|
|| $firstSix === 'remove'
|
|
|| $firstFour === 'nuke'
|
|
|| $firstEight === 'dropkick')
|
|
return ChangelogChange::ACTION_REMOVE;
|
|
|
|
return ChangelogChange::ACTION_UPDATE;
|
|
}
|
|
|
|
header('Content-Type: text/plain; charset=utf-8');
|
|
|
|
if($_SERVER['REQUEST_METHOD'] !== 'POST')
|
|
die('no');
|
|
|
|
$config = MSZ_ROOT . '/config/github.ini';
|
|
if(!is_file($config))
|
|
die('config missing');
|
|
|
|
$config = parse_ini_file(MSZ_ROOT . '/config/github.ini', true);
|
|
if(empty($config['tokens']['token']))
|
|
die('config invalid');
|
|
|
|
$isGitea = isset($_SERVER['HTTP_X_GITEA_DELIVERY']) && isset($_SERVER['HTTP_X_GITEA_EVENT']);
|
|
|
|
$rawData = file_get_contents('php://input');
|
|
$sigParts = $isGitea
|
|
? ['sha256', $_SERVER['HTTP_X_GITEA_SIGNATURE']]
|
|
: explode('=', $_SERVER['HTTP_X_HUB_SIGNATURE'] ?? '', 2);
|
|
|
|
if(empty($sigParts[1]))
|
|
die('invalid signature');
|
|
|
|
$repoAuthenticated = false;
|
|
foreach($config['tokens']['token'] as $repoName => $repoToken) {
|
|
if(hash_equals(hash_hmac($sigParts[0], $rawData, $repoToken), $sigParts[1])) {
|
|
$repoAuthenticated = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!$repoAuthenticated)
|
|
die('signature check failed');
|
|
|
|
$data = json_decode($_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded'
|
|
? $_POST['payload']
|
|
: $rawData);
|
|
|
|
if(empty($data))
|
|
die('body is corrupt');
|
|
|
|
if(empty($data->repository->full_name))
|
|
die('body is corrupt');
|
|
|
|
if($data->repository->full_name !== $repoName)
|
|
die('invalid repository token');
|
|
|
|
if($_SERVER['HTTP_X_GITHUB_EVENT'] !== 'push')
|
|
die('only push event is supported');
|
|
|
|
$commitCount = count($data->commits);
|
|
if($commitCount < 1)
|
|
die('no commits received');
|
|
|
|
$repoInfo = $config['repo:' . $repoName] ?? [];
|
|
|
|
$repoMaster = 'refs/heads/master';
|
|
if(!empty($repoInfo['master']))
|
|
$repoMaster = $repoInfo['master'];
|
|
|
|
if($data->ref !== $repoMaster)
|
|
die('only the master branch is tracked');
|
|
|
|
// the actual changelog api sucks ass
|
|
$changeCreate = DB::prepare('INSERT INTO `msz_changelog_changes` (`change_log`, `change_text`, `change_action`, `user_id`, `change_created`) VALUES (:log, :text, :action, :user, FROM_UNIXTIME(:created))');
|
|
$changeTag = DB::prepare('REPLACE INTO `msz_changelog_change_tags` VALUES (:change_id, :tag_id)');
|
|
|
|
$tags = $repoInfo['tags'] ?? [];
|
|
$addresses = $config['addresses'] ?? [];
|
|
|
|
foreach($data->commits as $commit) {
|
|
$message = trim($commit->message);
|
|
|
|
if(mb_strpos($message, $repoName) !== false
|
|
|| mb_substr($message, 0, 2) === '//'
|
|
|| mb_strpos(mb_strtolower($message), 'merge pull request') !== false)
|
|
continue;
|
|
|
|
$index = mb_strpos($message, "\n");
|
|
$line = $index === false ? $message : mb_substr($message, 0, $index);
|
|
$body = trim($index === false ? '' : mb_substr($message, $index + 1));
|
|
|
|
$changeCreate->bind('user', $addresses[$commit->author->email] ?? null);
|
|
$changeCreate->bind('action', ghcb_changelog_action($line));
|
|
$changeCreate->bind('log', $line);
|
|
$changeCreate->bind('text', empty($body) ? null : $body);
|
|
$changeCreate->bind('created', max(1, strtotime($commit->timestamp)));
|
|
$changeId = $changeCreate->executeGetId();
|
|
|
|
if(!empty($tags) && !empty($changeId)) {
|
|
$changeTag->bind('change_id', $changeId);
|
|
|
|
foreach($tags as $tag) {
|
|
$changeTag->bind('tag_id', $tag);
|
|
$changeTag->execute();
|
|
}
|
|
}
|
|
|
|
unset($changeId, $tag);
|
|
}
|