143 lines
3.9 KiB
PHP
143 lines
3.9 KiB
PHP
<?php
|
|
namespace Misuzu;
|
|
|
|
if(!isset($msz) || !($msz instanceof \Misuzu\MisuzuContext))
|
|
die('Script must be called through the Misuzu route dispatcher.');
|
|
|
|
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): string {
|
|
$original = trim($line);
|
|
$line = ghcb_strip_prefix($line);
|
|
|
|
$firstSix = mb_strtolower(mb_substr($original, 0, 6));
|
|
|
|
if($firstSix === 'revert'
|
|
|| $firstSix === 'restor')
|
|
return 'revert';
|
|
if($firstSix === 'import')
|
|
return 'import';
|
|
|
|
$firstThree = mb_strtolower(mb_substr($original, 0, 3));
|
|
|
|
if($firstThree === 'add'
|
|
|| $firstSix === 'create')
|
|
return 'add';
|
|
if($firstThree === 'fix')
|
|
return '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 'remove';
|
|
|
|
return 'update';
|
|
}
|
|
|
|
header('Content-Type: text/plain; charset=utf-8');
|
|
|
|
if($_SERVER['REQUEST_METHOD'] !== 'POST')
|
|
die('no');
|
|
|
|
$config = MSZ_CONFIG . '/github.ini';
|
|
if(!is_file($config))
|
|
die('config missing');
|
|
|
|
$config = parse_ini_file($config, 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');
|
|
if(!is_string($rawData))
|
|
die('no input data');
|
|
|
|
$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(!isset($repoName) || !is_string($repoName))
|
|
die('no repo name');
|
|
|
|
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');
|
|
|
|
if(!property_exists($data, 'commits'))
|
|
die('commits property missing');
|
|
if(!property_exists($data, 'ref'))
|
|
die('ref property missing');
|
|
|
|
$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');
|
|
|
|
$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));
|
|
|
|
$changeInfo = $msz->changelog->createChange(
|
|
ghcb_changelog_action($line),
|
|
$line, $body,
|
|
$addresses[$commit->author->email] ?? null,
|
|
max(1, strtotime($commit->timestamp))
|
|
);
|
|
|
|
if(!empty($tags))
|
|
foreach($tags as $tag)
|
|
$msz->changelog->addTagToChange($changeInfo, $tag);
|
|
}
|