Page MenuHomeDevCentral

No OneTemporary

diff --git a/app/Analyzers/GitHubPayloadAnalyzer.php b/app/Analyzers/GitHub/GitHubPayloadAnalyzer.php
similarity index 99%
rename from app/Analyzers/GitHubPayloadAnalyzer.php
rename to app/Analyzers/GitHub/GitHubPayloadAnalyzer.php
index 813c49b..51f847e 100644
--- a/app/Analyzers/GitHubPayloadAnalyzer.php
+++ b/app/Analyzers/GitHub/GitHubPayloadAnalyzer.php
@@ -1,315 +1,315 @@
<?php
-namespace Nasqueron\Notifications\Analyzers;
+namespace Nasqueron\Notifications\Analyzers\GitHub;
use Config;
use Storage;
class GitHubPayloadAnalyzer {
///
/// Private members
///
/**
* The project name, used to load specific configuration and offer defaults
* @var string
*/
private $project;
/**
* The GitHub event triggering this request
* @var string
*/
private $event;
/**
* The request content, as a structured data
* @var stdClass
*/
private $payload;
/**
* The configuration for the payload analyzer
* @var GitHubPayloadAnalyzerConfiguration;
*/
private $configuration;
///
/// Constructor
///
/**
* Creates a new GitHubPayloadAnalyzer instance.
*
* @param string $project
* @param string $event
* @param stdClass $payload
*/
public function __construct($project, $event, $payload) {
$this->project = $project;
$this->event = $event;
$this->payload = $payload;
$this->loadConfiguration($project);
}
///
/// Configuration
///
const CONFIG_DEFAULT_FILE = 'default.json';
public function getConfigurationFileName () {
$dir = Config::get('services.github.analyzer.configDir');
$filename = $dir . '/' . $this->project . '.json';
if (!Storage::has($filename)) {
return $dir . '/' . static::CONFIG_DEFAULT_FILE;
}
return $filename;
}
public function loadConfiguration () {
$fileName = $this->getConfigurationFileName();
$mapper = new \JsonMapper();
$this->configuration = $mapper->map(
json_decode(Storage::get($fileName)),
new GitHubPayloadAnalyzerConfiguration()
);
}
///
/// Properties
///
public function getRepository () {
if ($this->isAdministrativeEvent()) {
return '';
}
return $this->payload->repository->name;
}
///
/// Qualification of the payload
///
public function isAdministrativeEvent () {
$administrativeEvents = [
'membership', // Member added to team
'ping', // Special ping pong event, fired on new hook
'repository', // Repository created
];
return in_array($this->event, $administrativeEvents);
}
/**
* Gets the group for a specific payload
*
* @return string the group, central part of the routing key
*/
public function getGroup () {
// Some events are organization-level only and can't be mapped to an
// existing repository.
if ($this->isAdministrativeEvent()) {
return $this->configuration->administrativeGroup;
}
// If the payload is about some repository matching a table of
// symbols, we need to sort it to the right group.
$repository = $this->getRepository();
foreach ($this->configuration->repositoryMapping as $mapping) {
if ($mapping->doesRepositoryBelong($repository)) {
return $mapping->group;
}
}
// By default, fallback group is the project name or a specified value.
if (empty($this->configuration->defaultGroup)) {
return strtolower($this->project);
}
return $this->configuration->defaultGroup;
}
///
/// Description of the payload
///
/**
* Gets repository and branch information
*
* @return string
*/
public function getWhere () {
$repo = $this->payload->repository->name;
$branch = $this->payload->ref;
return static::getRepositoryAndBranch($repo, $branch);
}
/**
* Gets a repository and branch information string
*
* @param string $repo The repository
* @param string $branch The branch
* @return string "<repo>" or "<repo> (branch <branch>)" when branch isn't master
*/
public static function getRepositoryAndBranch ($repo = "", $branch = "") {
if ($repo === "") {
return "";
}
if (starts_with($branch, "refs/heads/")) {
$branch = substr($branch, 11);
}
if ($branch === "" || $branch === "master") {
return $repo;
}
return "$repo (branch $branch)";
}
/**
* Gets the title of the head commit
*
* @return string
*/
private function getHeadCommitTitle () {
return static::getCommitTitle($this->payload->head_commit->message);
}
/**
* Extracts the commit title from the whole commit message.
*
* @param string $message The commit message
* @return string The commit title
*/
public static function getCommitTitle ($message) {
// Discards extra lines
$pos = strpos($message, "\n");
if ($pos > 0) {
$message = substr($message, 0, $pos);
}
// Short messages are returned as is
$len = strlen($message);
if ($len <= 72) {
return $message;
}
// Longer messages are truncated
return substr($message, 0, 71) . '…';
}
/**
* Gets the description text for the head commit.
*
* @return string
*/
private function getHeadCommitDescription () {
$commit = $this->payload->head_commit;
$title = $this->getHeadCommitTitle();
$committer = $commit->committer->username;
$author = $commit->author->username;
$message = "$committer committed $title";
if ($committer !== $author) {
$message .= " (authored by $author)";
}
return $message;
}
/**
* Gets a short textual description of the event
*
* @return string
*/
public function getDescription () {
switch ($this->event) {
case "create":
$repository = $this->payload->repository->full_name;
$type = $this->payload->ref_type;
$ref = $this->payload->ref;
if ($type == "tag" || $type == "branch") {
return "New $type on $repository: $ref";
}
return "Unknown create: $type $ref";
case "ping":
$quote = $this->payload->zen;
return "« $quote » — GitHub Webhooks ping zen aphorism.";
case "push":
$n = count($this->payload->commits);
if ($n == 1) {
return $this->getHeadCommitDescription();
}
$repoAndBranch = $this->getWhere();
$user = $this->payload->pusher->name;
return "$user pushed $n commits to $repoAndBranch";
case "repository":
$repository = $this->payload->repository->full_name;
$message = "New repository $repository";
if ($this->payload->repository->fork) {
$message .= " (fork)";
}
if ($description = $this->payload->repository->description) {
$message .= " — $description";
}
return $message;
case "status":
return $this->payload->description
. " — "
. $this->payload->context;
default:
return "Some $this->event happened";
}
}
/**
* Gets a link to view the event on GitHub
*
* @return string The most relevant URL
*/
public function getLink () {
switch ($this->event) {
case "create":
$type = $this->payload->ref_type;
$ref = $this->payload->ref;
$url = $this->payload->repository->html_url;
if ($type == "tag") {
$url .= "/releases/tag/" . $ref;
} elseif ($type == "branch") {
$url .= "/tree/" . $ref;
}
return $url;
case "push":
$n = count($this->payload->commits);
if ($n == 1) {
return $this->payload->head_commit->url;
}
return $this->payload->compare;
case "repository":
return $this->payload->repository->html_url;
case "status":
return $this->payload->target_url;
default:
return "";
}
}
}
diff --git a/app/Analyzers/GitHubPayloadAnalyzerConfiguration.php b/app/Analyzers/GitHub/GitHubPayloadAnalyzerConfiguration.php
similarity index 90%
rename from app/Analyzers/GitHubPayloadAnalyzerConfiguration.php
rename to app/Analyzers/GitHub/GitHubPayloadAnalyzerConfiguration.php
index f0eef2b..d75a89f 100644
--- a/app/Analyzers/GitHubPayloadAnalyzerConfiguration.php
+++ b/app/Analyzers/GitHub/GitHubPayloadAnalyzerConfiguration.php
@@ -1,26 +1,26 @@
<?php
-namespace Nasqueron\Notifications\Analyzers;
+namespace Nasqueron\Notifications\Analyzers\GitHub;
class GitHubPayloadAnalyzerConfiguration {
/**
* The group for organization only events
*
* @var string
*/
public $administrativeGroup;
/**
* The default group to fallback for any event not mapped in another group
*
* @var string
*/
public $defaultGroup;
/**
* An array of RepositoryGroupMapping objects to match repositories & groups
*
* @var RepositoryGroupMapping[]
*/
public $repositoryMapping;
}
diff --git a/app/Analyzers/RepositoryGroupMapping.php b/app/Analyzers/GitHub/RepositoryGroupMapping.php
similarity index 96%
rename from app/Analyzers/RepositoryGroupMapping.php
rename to app/Analyzers/GitHub/RepositoryGroupMapping.php
index 01c6bf0..6204abf 100644
--- a/app/Analyzers/RepositoryGroupMapping.php
+++ b/app/Analyzers/GitHub/RepositoryGroupMapping.php
@@ -1,53 +1,53 @@
<?php
-namespace Nasqueron\Notifications\Analyzers;
+namespace Nasqueron\Notifications\Analyzers\GitHub;
class RepositoryGroupMapping {
///
/// Properties
///
/**
* The group the mapped repositories belong to
*
* @var string
*/
public $group;
/**
* An array of the repositories, each item a string with the name of the
* repository. The wildcard '*' is allowed to specify several repositories.
*
* @var array
*/
public $repositories;
///
/// Helper methods
///
/**
* Determines if the specified repository matches a pattern
*
* @param string $pattern The pattern, with * allowed as wildcard character
* @param string $repository The repository name to compare with the pattern
* @return bool
*/
public static function doesRepositoryMatch ($pattern, $repository) {
return str_is($pattern, $repository);
}
/**
* Determines if the specified repository belong to this mapping
*
* @return bool
*/
public function doesRepositoryBelong ($actualRepository) {
foreach ($this->repositories as $candidateRepository) {
if (static::doesRepositoryMatch($candidateRepository, $actualRepository)) {
return true;
}
}
return false;
}
}
diff --git a/app/Listeners/AMQPEventListener.php b/app/Listeners/AMQPEventListener.php
index 40332bd..73a1536 100644
--- a/app/Listeners/AMQPEventListener.php
+++ b/app/Listeners/AMQPEventListener.php
@@ -1,140 +1,140 @@
<?php
namespace Nasqueron\Notifications\Listeners;
use Nasqueron\Notifications\Events\GitHubPayloadEvent;
use Nasqueron\Notifications\Events\NotificationEvent;
-use Nasqueron\Notifications\Analyzers\GitHubPayloadAnalyzer;
+use Nasqueron\Notifications\Analyzers\GitHub\GitHubPayloadAnalyzer;
use Nasqueron\Notifications\Jobs\SendMessageToBroker;
use Nasqueron\Notifications\Notification;
use Config;
class AMQPEventListener {
///
/// GitHub events
///
/**
* Gets routing key, to allow consumers to select the topic they subscribe to.
*
* @param GitHubPayloadEvent $event the payload event
*/
protected static function getGitHubEventRoutingKey (GitHubPayloadEvent $event) {
$key = [
strtolower($event->door),
self::getGroup($event),
$event->event
];
return implode('.', $key);
}
protected static function getAnalyzer (GitHubPayloadEvent $event) {
return new GitHubPayloadAnalyzer(
$event->door,
$event->event,
$event->payload
);
}
/**
* Gets the group for a specific payload
*
* @return string the group, central part of the routing key
*/
protected static function getGroup (GitHubPayloadEvent $event) {
$analyzer = self::getAnalyzer($event);
return $analyzer->getGroup();
}
/**
* Handles a GitHub payload event.
*
* @param GitHubPayloadEvent $event
* @return void
*/
public function onGitHubPayload(GitHubPayloadEvent $event) {
$this->sendRawPayload($event);
}
/**
* This is our gateway GitHub Webhooks -> Broker
*
* @param GitHubPayloadEvent $event
*/
protected function sendRawPayload(GitHubPayloadEvent $event) {
$target = Config::get('broker.targets.github_events');
$routingKey = static::getGitHubEventRoutingKey($event);
$message = json_encode($event->payload);
$job = new SendMessageToBroker($target, $routingKey, $message);
$job->handle();
}
///
/// Notifications
///
/**
* Handles a notification event.
*
* @param NotificationEvent $event
* @return void
*/
public function onNotification(NotificationEvent $event) {
$this->sendNotification($event);
}
/**
* Gets routing key, to allow consumers to select the topic they subscribe to.
*
* @param NotificationEvent $event
*/
protected static function getNotificationRoutingKey (Notification $notification) {
$key = [
$notification->project,
$notification->group,
$notification->service,
$notification->type
];
return strtolower(implode('.', $key));
}
/**
* This is our gateway specialized for distilled notifications
*
* @param NotificationEvent $event
*/
protected function sendNotification(NotificationEvent $event) {
$notification = $event->notification;
$target = Config::get('broker.targets.notifications');
$routingKey = static::getNotificationRoutingKey($notification);
$message = json_encode($notification);
$job = new SendMessageToBroker($target, $routingKey, $message);
$job->handle();
}
///
/// Events listening
///
/**
* Register the listeners for the subscriber.
*
* @param Illuminate\Events\Dispatcher $events
*/
public function subscribe (\Illuminate\Events\Dispatcher $events) {
$class = 'Nasqueron\Notifications\Listeners\AMQPEventListener';
$events->listen(
'Nasqueron\Notifications\Events\GitHubPayloadEvent',
"$class@onGitHubPayload"
);
$events->listen(
'Nasqueron\Notifications\Events\NotificationEvent',
"$class@onNotification"
);
}
}
diff --git a/app/Notifications/GitHubNotification.php b/app/Notifications/GitHubNotification.php
index 58e56b1..5b44b5c 100644
--- a/app/Notifications/GitHubNotification.php
+++ b/app/Notifications/GitHubNotification.php
@@ -1,69 +1,69 @@
<?php
namespace Nasqueron\Notifications\Notifications;
-use Nasqueron\Notifications\Analyzers\GitHubPayloadAnalyzer;
+use Nasqueron\Notifications\Analyzers\GitHub\GitHubPayloadAnalyzer;
use Nasqueron\Notifications\Notification;
class GitHubNotification extends Notification {
/**
* @var GitHubPayloadAnalyzer
*/
private $analyzer = null;
public function __construct ($project, $event, $payload) {
// Straightforward properties
$this->service = "GitHub";
$this->project = $project;
$this->type = $event;
$this->rawContent = $payload;
// Analyzes and fills
$this->group = $this->getGroup();
$this->text = $this->getText();
$this->link = $this->getLink();
}
/**
* Gets analyzer
*/
private function getAnalyzer () {
if ($this->analyzer === null) {
$this->analyzer = new GitHubPayloadAnalyzer(
$this->project,
$this->type,
$this->rawContent
);
}
return $this->analyzer;
}
/**
* Gets the target notificatrion group
*
* @return string the target group for the notification
*/
public function getGroup () {
return $this->getAnalyzer()->getGroup();
}
/**
* Gets the notification text. Intended to convey a short message (thing Twitter or IRC).
*
* @return string
*/
public function getText () {
return $this->getAnalyzer()->getDescription();
}
/**
* Gets the notification URL. Intended to be a widget or icon link.
*
* @return string
*/
public function getLink () {
return $this->getAnalyzer()->getLink();
}
}
diff --git a/tests/Analyzers/GitHubPayloadAnalyzerTest.php b/tests/Analyzers/GitHubPayloadAnalyzerTest.php
index b6f2b61..e86968e 100644
--- a/tests/Analyzers/GitHubPayloadAnalyzerTest.php
+++ b/tests/Analyzers/GitHubPayloadAnalyzerTest.php
@@ -1,76 +1,76 @@
<?php
namespace Nasqueron\Notifications\Tests\Analyzers;
use Illuminate\Foundation\Testing\WithoutMiddleware;
-use Nasqueron\Notifications\Analyzers\GitHubPayloadAnalyzer;
-use Nasqueron\Notifications\Analyzers\GitHubPayloadAnalyzerConfiguration;
+use Nasqueron\Notifications\Analyzers\GitHub\GitHubPayloadAnalyzer;
+use Nasqueron\Notifications\Analyzers\GitHub\GitHubPayloadAnalyzerConfiguration;
use Nasqueron\Notifications\Tests\TestCase;
class GitHubPayloadAnalyzerConfigurationTest extends TestCase {
/**
* Configuration
*
- * @var Nasqueron\Notifications\Analyzers\GitHubPayloadAnalyzerConfiguration
+ * @var Nasqueron\Notifications\Analyzers\GitHub\GitHubPayloadAnalyzerConfiguration
*/
protected $configuration;
/**
* Prepares the test
*/
public function setUp () {
$filename = __DIR__ . '/../data/GitHubPayloadAnalyzer/Nasqueron.json';
$mapper = new \JsonMapper();
$this->configuration = $mapper->map(
json_decode(file_get_contents($filename)),
new GitHubPayloadAnalyzerConfiguration()
);
}
/**
* Determines the JSON object is well parsed
*/
public function testProperties () {
$this->assertEquals("orgz", $this->configuration->administrativeGroup);
$this->assertEquals("nasqueron", $this->configuration->defaultGroup);
foreach ($this->configuration->repositoryMapping as $item) {
$this->assertInstanceOf(
- 'Nasqueron\Notifications\Analyzers\RepositoryGroupMapping',
+ 'Nasqueron\Notifications\Analyzers\GitHub\RepositoryGroupMapping',
$item
);
}
}
public function testGetCommitTitle () {
$this->assertEquals("", GitHubPayloadAnalyzer::getCommitTitle(""));
$this->assertEquals("Lorem ipsum dolor", GitHubPayloadAnalyzer::getCommitTitle("Lorem ipsum dolor"));
$longCommitMessages = [
"I was born in a water moon. Some people, especially its inhabitants, called it a planet, but as it was only a little over two hundred kilometres in diameter, 'moon' seems the more accurate term. The moon was made entirely of water, by which I mean it was a globe that not only had no land, but no rock either, a sphere with no solid core at all, just liquid water, all the way down to the very centre of the globe.",
"I was born in a water moon. Some people, especially its inhabitants, called it a planet, but as it was only a little over two hundred kilometres in diameter, 'moon' seems the more accurate term. The moon was made entirely of water, by which I mean it was a globe that not only had no land, but no rock either, a sphere with no solid core at all, just liquid water, all the way down to the very centre of the globe.\n\nIf it had been much bigger the moon would have had a core of ice, for water, though supposedly incompressible, is not entirely so, and will change under extremes of pressure to become ice. (If you are used to living on a planet where ice floats on the surface of water, this seems odd and even wrong, but nevertheless it is the case.) The moon was not quite of a size for an ice core to form, and therefore one could, if one was sufficiently hardy, and adequately proof against the water pressure, make one's way down, through the increasing weight of water above, to the very centre of the moon.",
];
$shortCommitTitle = "I was born in a water moon. Some people, especially its inhabitants, ca…";
foreach ($longCommitMessages as $longCommitMessage) {
$this->assertEquals(
$shortCommitTitle,
GitHubPayloadAnalyzer::getCommitTitle($longCommitMessage)
);
}
}
public function testGetRepositoryAndBranch () {
$this->assertEquals("", GitHubPayloadAnalyzer::getRepositoryAndBranch("", "master"));
$this->assertEquals("", GitHubPayloadAnalyzer::getRepositoryAndBranch("", "foo"));
$this->assertEquals("quux", GitHubPayloadAnalyzer::getRepositoryAndBranch("quux", "master"));
$this->assertEquals("quux", GitHubPayloadAnalyzer::getRepositoryAndBranch("quux", "refs/heads/master"));
$this->assertEquals("quux", GitHubPayloadAnalyzer::getRepositoryAndBranch("quux", ""));
$this->assertEquals("quux (branch foo)", GitHubPayloadAnalyzer::getRepositoryAndBranch("quux", "refs/heads/foo"));
$this->assertEquals("quux (branch feature/foo)", GitHubPayloadAnalyzer::getRepositoryAndBranch("quux", "refs/heads/feature/foo"));
$this->assertEquals("quux (branch feature/foo)", GitHubPayloadAnalyzer::getRepositoryAndBranch("quux", "feature/foo"));
$this->assertEquals("quux (branch foo)", GitHubPayloadAnalyzer::getRepositoryAndBranch("quux", "foo"));
$this->assertEquals("quux (branch 0)", GitHubPayloadAnalyzer::getRepositoryAndBranch("quux", "0"));
}
}
diff --git a/tests/Analyzers/RepositoryGroupMappingTest.php b/tests/Analyzers/RepositoryGroupMappingTest.php
index ed36853..965e36a 100644
--- a/tests/Analyzers/RepositoryGroupMappingTest.php
+++ b/tests/Analyzers/RepositoryGroupMappingTest.php
@@ -1,48 +1,48 @@
<?php
namespace Nasqueron\Notifications\Tests\Analyzers;
use Illuminate\Foundation\Testing\WithoutMiddleware;
-use Nasqueron\Notifications\Analyzers\RepositoryGroupMapping;
+use Nasqueron\Notifications\Analyzers\GitHub\RepositoryGroupMapping;
use Nasqueron\Notifications\Tests\TestCase;
class RepositoryGroupMappingTest extends TestCase {
public function testDoesRepositoryMatch () {
$this->assertTrue(
RepositoryGroupMapping::doesRepositoryMatch(
'quux*',
'quuxians'
)
);
$this->assertTrue(
RepositoryGroupMapping::doesRepositoryMatch(
'quux*',
'quux'
)
);
$this->assertFalse(
RepositoryGroupMapping::doesRepositoryMatch(
'foobar',
'quux'
)
);
$this->assertFalse(
RepositoryGroupMapping::doesRepositoryMatch(
'',
'quuxians'
)
);
$this->assertFalse(
RepositoryGroupMapping::doesRepositoryMatch(
'quux*',
''
)
);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Aug 18, 23:10 (1 d, 20 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3993223
Default Alt Text
(24 KB)

Event Timeline