<?php
namespace App\Subscriber;
use App\Services\Discord\DiscordMessageService;
use Smalot\Bitbucket\Webhook\Event\EventBase;
use Smalot\Bitbucket\Webhook\Event\RepoCommitStatusCreatedEvent;
use Smalot\Bitbucket\Webhook\Event\RepoCommitStatusUpdatedEvent;
use Smalot\Bitbucket\Webhook\Event\RepoPushEvent;
use Smalot\Bitbucket\Webhook\Model\RepoPushModel;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class BitbucketEventSubscriber implements EventSubscriberInterface
{
const COMMIT_STATUS_INPROGRESS = 'INPROGRESS';
const COMMIT_STATUS_SUCCESSFUL = 'SUCCESSFUL';
const COMMIT_STATUS_FAILED = 'FAILED';
const COMMIT_TAGGED_SUCCESSFUL = 'has new version';
const COLOR_RED = '#ED4245';
const COLOR_BLUE = '#5865F2';
const COLOR_GREEN = '#57F287';
private DiscordMessageService $discordMessageService;
public function __construct(DiscordMessageService $discordMessageService)
{
$this->discordMessageService = $discordMessageService;
}
public static function getSubscribedEvents()
{
// return the subscribed events, their methods and priorities
return [
RepoCommitStatusUpdatedEvent::class => 'onCommitStatusChanged',
RepoCommitStatusCreatedEvent::class => 'onCommitStatusChanged',
RepoPushEvent::class => 'onRepoPush',
];
}
public function onRepoPush(EventBase $event): void
{
/** @var RepoPushModel $model */
$model = $event->getData();
$repository = $model->getRepository();
$push = $model->getPush();
if (
!empty($repository['project']['name']) &&
!empty($repository['name']) &&
!empty($push['changes'])
) {
foreach ($push['changes'] as $change) {
if (!empty($change['new']['type']) && $change['new']['type'] === 'tag' && !empty($change['new']['name'])) {
$this->sendDiscordNotification(
$repository['project']['name'],
$repository['name'],
null,
self::COMMIT_TAGGED_SUCCESSFUL,
$change['new']['name']
);
}
}
}
}
public function onCommitStatusChanged(EventBase $event): void
{
$repository = $event->getData()->getRepository();
$commitStatus = $event->getData()->getCommitStatus();
if (
!empty($repository['project']['name']) &&
!empty($repository['name']) &&
!empty($commitStatus['refname']) &&
!empty($commitStatus['name']) &&
!empty($commitStatus['state'])
) {
$this->sendDiscordNotification(
$repository['project']['name'],
$repository['name'],
$commitStatus['refname'],
$commitStatus['name'],
$commitStatus['state']
);
}
}
private function isAcceptableBranch(string $branch): bool
{
return $branch === "master" || preg_match('/^v\d+\.x$/',$branch);
}
private function sendDiscordNotification(string $project, string $repository, ?string $branch, string $status, string $state): void
{
if ( $branch === null || $this->isAcceptableBranch($branch) ) {
$message = ':bulb: ';
if ( $state === self::COMMIT_STATUS_SUCCESSFUL ) {
$message .= ':white_check_mark: ';
}
elseif ( $state === self::COMMIT_STATUS_FAILED ) {
$message .= ':no_entry_sign: ';
}
else {
$message .= ':information_source: ';
}
$message .= '**' . $project . ' / ' . $repository . ':** '.$status.' `'.$state.'`';
$this->discordMessageService->send($message);
}
}
}