Page MenuHomeDevCentral

No OneTemporary

diff --git a/app/Jobs/NotifyNewCommitsToDiffusion.php b/app/Jobs/NotifyNewCommitsToDiffusion.php
index 336f4df..b1ada61 100644
--- a/app/Jobs/NotifyNewCommitsToDiffusion.php
+++ b/app/Jobs/NotifyNewCommitsToDiffusion.php
@@ -1,196 +1,201 @@
<?php
namespace Nasqueron\Notifications\Jobs;
use Nasqueron\Notifications\Actions\ActionError;
use Nasqueron\Notifications\Actions\NotifyNewCommitsAction;
use Nasqueron\Notifications\Events\ReportEvent;
use Nasqueron\Notifications\Phabricator\PhabricatorAPI as API;
use Nasqueron\Notifications\Phabricator\PhabricatorAPIException;
-
use Event;
use Log;
use PhabricatorAPI;
+use RuntimeException;
+
/**
* This class allows to notify Phabricator of new commits, so daemons can pull
* these new commits and add them into Diffusion.
*/
class NotifyNewCommitsToDiffusion extends Job {
///
/// Private members
///
/**
* The clone URL of the repository
*
* @var string
*/
private $repository;
/**
* @var \Nasqueron\Notifications\Phabricator\PhabricatorAPI
*/
private $api;
/**
* @var string
*/
private $callSign;
/**
* @var NotifyNewCommitsAction
*/
private $actionToReport;
/**
* @var string
*/
private $sourceProject;
///
/// Constructor
///
/**
* Initializes a new instance of NotifyNewCommitsToDiffusion.
*/
public function __construct ($sourceProject, $repository) {
$this->sourceProject = $sourceProject;
$this->repository = $repository;
}
///
/// Task
///
/**
* Executes the job.
*
* @return void
*/
public function handle () : void {
if (!$this->fetchRequirements()) {
return;
}
$this->initializeReport();
$this->notifyPhabricator();
$this->sendReport();
}
/**
* Initializes the actions report.
*/
private function initializeReport () : void {
$this->actionToReport = new NotifyNewCommitsAction($this->callSign);
}
/**
* Notifies Phabricator to pull from the repository.
*/
private function notifyPhabricator () : void {
try {
$this->callDiffusionLookSoon();
} catch (PhabricatorAPIException $ex) {
$actionError = new ActionError($ex);
$this->actionToReport->attachError($actionError);
Log::error($ex);
}
}
/**
* Fires a report event with the actions report.
*/
private function sendReport () : void {
$event = new ReportEvent($this->actionToReport);
Event::fire($event);
}
///
/// Helper methods to find correct Phabricator instance and get the API
///
/**
* Gets the relevant Phabricator project for the specified source project.
*
* @return string The Phabricator project name
*/
private function getPhabricatorProject () : string {
return $this->sourceProject;
}
///
/// Helper methods to populate object members
///
/**
* Fetches API and call sign.
*
* @return bool true if all requirement have been fetched ; otherwise, false.
*/
private function fetchRequirements () : bool {
return $this->fetchAPI() && $this->fetchCallSign();
}
/**
* Fetches the Phabricator API to use for the current source project.
*
* @return bool true if an API instance has been fetch ; otherwise, false.
*/
private function fetchAPI () : bool {
$project = $this->getPhabricatorProject();
- $this->api = PhabricatorAPI::getForProject($project);
- return $this->api !== null;
+ try {
+ $this->api = PhabricatorAPI::getForProject($project);
+ return true;
+ } catch (RuntimeException $ex) {
+ return false;
+ }
}
/**
* Fetches the call sign matching the repository.
*
* @return bool true if a call sign have been found ; otherwise, false.
*/
private function fetchCallSign () : bool {
$this->callSign = $this->getCallSign();
return $this->callSign !== "";
}
///
/// Helper methods to query Phabricator API
///
/**
* Gets the call sign matching the repository URL.
*
* @return string the repository call sign "OPS", or "" if not in Phabricator
*/
private function getCallSign () : string {
$reply = $this->api->call(
'repository.query',
[ 'remoteURIs[0]' => $this->repository ]
);
if (!count($reply)) {
return "";
}
return API::getFirstResult($reply)->callsign;
}
/**
* Calls the diffusion.looksoon API method.
*
* @throws PhabricatorAPIException
*/
private function callDiffusionLookSoon () : void {
$this->api->call(
'diffusion.looksoon',
[ 'callsigns[0]' => $this->callSign ]
);
}
}
diff --git a/tests/Jobs/NotifyNewCommitsToDiffusionTest.php b/tests/Jobs/NotifyNewCommitsToDiffusionTest.php
index 5c9f228..9051d5a 100644
--- a/tests/Jobs/NotifyNewCommitsToDiffusionTest.php
+++ b/tests/Jobs/NotifyNewCommitsToDiffusionTest.php
@@ -1,44 +1,70 @@
<?php
namespace Nasqueron\Notifications\Tests\Jobs;
+use Nasqueron\Notifications\Jobs\Job;
use Nasqueron\Notifications\Jobs\NotifyNewCommitsToDiffusion;
-use Nasqueron\Notifications\Phabricator\PhabricatorAPI;
use Nasqueron\Notifications\Tests\TestCase;
-use Mockery;
-
class NotifyNewCommitsToDiffusionTest extends TestCase {
- /**
- * Mock for the Phabricator API factory
- * @var \Mockery\MockInterface
- */
- private $apiFactoryMock;
+ ///
+ /// Tests
+ ///
/**
- * The job to test
- * @var NotifyNewCommitsToDiffusion
+ * @dataProvider apiRepositoryReplyProvider
*/
- private $job;
+ public function testHandle ($apiRepositoryReply, int $apiCallCounts) {
+ $this->mockPhabricatorAPI()
+ ->shouldReceive('getForProject->call')
+ ->andReturn(
+ // First API call: repository.query
+ $apiRepositoryReply,
- public function setUp () {
- parent::setUp();
+ // Second API call: diffusion.looksoon
+ null
+ )
+ ->times($apiCallCounts); // 2 when repository.query is valid
+ // 1 otherwise
+
+ $job = $this->mockJob();
+ $job->handle();
+ }
- $this->apiFactoryMock = $this->mockPhabricatorAPI();
- $this->job = $this->mockJob();
+ public function testJobWhenThereIsNoPhabricatorInstanceForTheProject () {
+ $job = $this->mockJob("not-existing-project");
+ $job->handle();
}
+ ///
+ /// Helper methods
+ ///
+
/**
- * @return NotifyNewCommitsToDiffusion
+ * Mocks a job
*/
- protected function mockJob() {
- return new NotifyNewCommitsToDiffusion("acme", "ssh://acme/k2.git");
+ protected function mockJob(string $project = "acme") : Job {
+ return new NotifyNewCommitsToDiffusion(
+ $project,
+ "ssh://acme/k2.git"
+ );
}
- public function testJobWantsPhabricatorAPI () {
- $this->apiFactoryMock->shouldReceive('getForProject')->once();
- $this->job->handle();
+ /**
+ * Provides API repository reply and associated API calls count
+ */
+ public function apiRepositoryReplyProvider () : array {
+ return [
+ // Regular behavior
+ [[new class { public $callsign = "K2"; }], 2],
+
+ // Phabricator doesn't know this repo
+ [[], 1],
+
+ // Some error occurs and the API reply is null
+ [null, 1],
+ ];
}
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Sep 18, 02:07 (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2989789
Default Alt Text
(7 KB)

Event Timeline