Moved webhook handler for changelog into Misuzu.
This commit is contained in:
parent
284230a84c
commit
70e340be34
5 changed files with 160 additions and 4 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,6 +6,7 @@
|
|||
|
||||
# Configuration
|
||||
/config/config.ini
|
||||
/config/github.ini
|
||||
/.debug
|
||||
/.migrating
|
||||
|
||||
|
|
9
config/github.example.ini
Normal file
9
config/github.example.ini
Normal file
|
@ -0,0 +1,9 @@
|
|||
[tokens]
|
||||
token[flashwave/misuzu] = token-here
|
||||
|
||||
[addresses]
|
||||
github@flash.moe = 1
|
||||
|
||||
[repo:flashwave/misuzu]
|
||||
tags[] = 1
|
||||
tags[] = 3
|
146
public/_github-callback.php
Normal file
146
public/_github-callback.php
Normal file
|
@ -0,0 +1,146 @@
|
|||
<?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 ? null : 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->bindValue('change_id', $changeId);
|
||||
|
||||
foreach($tags as $tag) {
|
||||
$changeTag->bindValue('tag_id', $tag);
|
||||
$changeTag->execute();
|
||||
}
|
||||
}
|
||||
|
||||
unset($changeId, $tag);
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
<div class="changelog__change__info">
|
||||
<div class="changelog__change__info__background"></div>
|
||||
<div class="changelog__change__info__content">
|
||||
{% if change_info.user.id is not null %}
|
||||
{% if change_info.user.id|default(null) is not null %}
|
||||
<div class="changelog__change__user">
|
||||
<a class="changelog__change__avatar" href="{{ url('user-profile', {'user': change_info.user.id}) }}">
|
||||
{{ avatar(change_info.user.id, 60, change_info.user.username) }}
|
||||
|
|
|
@ -49,10 +49,10 @@
|
|||
|
||||
{% if not is_small %}
|
||||
<a class="changelog__entry__user"
|
||||
href="{{ url(is_manage ? 'manage-user' : 'user-profile', {'user': change.user.id}) }}"
|
||||
style="--user-colour: {{ change.user.colour }}">
|
||||
href="{{ url(is_manage ? 'manage-user' : 'user-profile', {'user': change.user.id|default(0)}) }}"
|
||||
style="--user-colour: {{ change.user.colour|default('inherit') }}">
|
||||
<div class="changelog__entry__user__text">
|
||||
{{ change.user.username }}
|
||||
{{ change.user.username|default('Anonymous') }}
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
|
Loading…
Add table
Reference in a new issue