Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15401042
D16360.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
15 KB
Referenced Files
None
Subscribers
None
D16360.diff
View Options
diff --git a/src/applications/differential/herald/HeraldDifferentialRevisionAdapter.php b/src/applications/differential/herald/HeraldDifferentialRevisionAdapter.php
--- a/src/applications/differential/herald/HeraldDifferentialRevisionAdapter.php
+++ b/src/applications/differential/herald/HeraldDifferentialRevisionAdapter.php
@@ -20,6 +20,21 @@
return new DifferentialRevision();
}
+ public function isTestAdapterForObject($object) {
+ return ($object instanceof DifferentialRevision);
+ }
+
+ public function getAdapterTestDescription() {
+ return pht(
+ 'Test rules which run when a revision is created or updated.');
+ }
+
+ public function newTestAdapter($object) {
+ return self::newLegacyAdapter(
+ $object,
+ $object->loadActiveDiff());
+ }
+
protected function initializeNewAdapter() {
$this->revision = $this->newObject();
}
diff --git a/src/applications/diffusion/herald/HeraldCommitAdapter.php b/src/applications/diffusion/herald/HeraldCommitAdapter.php
--- a/src/applications/diffusion/herald/HeraldCommitAdapter.php
+++ b/src/applications/diffusion/herald/HeraldCommitAdapter.php
@@ -27,10 +27,24 @@
return new PhabricatorRepositoryCommit();
}
+ public function isTestAdapterForObject($object) {
+ return ($object instanceof PhabricatorRepositoryCommit);
+ }
+
+ public function getAdapterTestDescription() {
+ return pht(
+ 'Test rules which run after a commit is discovered and imported.');
+ }
+
protected function initializeNewAdapter() {
$this->commit = $this->newObject();
}
+ public function setObject($object) {
+ $this->commit = $object;
+ return $this;
+ }
+
public function getObject() {
return $this->commit;
}
diff --git a/src/applications/diffusion/herald/HeraldPreCommitAdapter.php b/src/applications/diffusion/herald/HeraldPreCommitAdapter.php
--- a/src/applications/diffusion/herald/HeraldPreCommitAdapter.php
+++ b/src/applications/diffusion/herald/HeraldPreCommitAdapter.php
@@ -25,6 +25,20 @@
return 'PhabricatorDiffusionApplication';
}
+ public function isTestAdapterForObject($object) {
+ return ($object instanceof PhabricatorRepositoryCommit);
+ }
+
+ public function canCreateTestAdapterForObject($object) {
+ return false;
+ }
+
+ public function getAdapterTestDescription() {
+ return pht(
+ 'Commit hook events depend on repository state which is only available '.
+ 'at push time, and can not be run in test mode.');
+ }
+
protected function initializeNewAdapter() {
$this->log = new PhabricatorRepositoryPushLog();
}
diff --git a/src/applications/herald/adapter/HeraldAdapter.php b/src/applications/herald/adapter/HeraldAdapter.php
--- a/src/applications/herald/adapter/HeraldAdapter.php
+++ b/src/applications/herald/adapter/HeraldAdapter.php
@@ -189,7 +189,6 @@
abstract public function getAdapterApplicationClass();
abstract public function getObject();
-
/**
* Return a new characteristic object for this adapter.
*
@@ -217,6 +216,23 @@
return false;
}
+ public function isTestAdapterForObject($object) {
+ return false;
+ }
+
+ public function canCreateTestAdapterForObject($object) {
+ return $this->isTestAdapterForObject($object);
+ }
+
+ public function newTestAdapter($object) {
+ return id(clone $this)
+ ->setObject($object);
+ }
+
+ public function getAdapterTestDescription() {
+ return null;
+ }
+
public function explainValidTriggerObjects() {
return pht('This adapter can not trigger on objects.');
}
diff --git a/src/applications/herald/controller/HeraldTestConsoleController.php b/src/applications/herald/controller/HeraldTestConsoleController.php
--- a/src/applications/herald/controller/HeraldTestConsoleController.php
+++ b/src/applications/herald/controller/HeraldTestConsoleController.php
@@ -2,14 +2,76 @@
final class HeraldTestConsoleController extends HeraldController {
+ private $testObject;
+ private $testAdapter;
+
+ public function setTestObject($test_object) {
+ $this->testObject = $test_object;
+ return $this;
+ }
+
+ public function getTestObject() {
+ return $this->testObject;
+ }
+
+ public function setTestAdapter(HeraldAdapter $test_adapter) {
+ $this->testAdapter = $test_adapter;
+ return $this;
+ }
+
+ public function getTestAdapter() {
+ return $this->testAdapter;
+ }
+
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
- $object_name = trim($request->getStr('object_name'));
+
+ $response = $this->loadTestObject($request);
+ if ($response) {
+ return $response;
+ }
+
+ $response = $this->loadAdapter($request);
+ if ($response) {
+ return $response;
+ }
+
+ $object = $this->getTestObject();
+ $adapter = $this->getTestAdapter();
+
+ $adapter->setIsNewObject(false);
+
+ $rules = id(new HeraldRuleQuery())
+ ->setViewer($viewer)
+ ->withContentTypes(array($adapter->getAdapterContentType()))
+ ->withDisabled(false)
+ ->needConditionsAndActions(true)
+ ->needAppliedToPHIDs(array($object->getPHID()))
+ ->needValidateAuthors(true)
+ ->execute();
+
+ $engine = id(new HeraldEngine())
+ ->setDryRun(true);
+
+ $effects = $engine->applyRules($rules, $adapter);
+ $engine->applyEffects($effects, $adapter, $rules);
+
+ $xscript = $engine->getTranscript();
+
+ return id(new AphrontRedirectResponse())
+ ->setURI('/herald/transcript/'.$xscript->getID().'/');
+ }
+
+ private function loadTestObject(AphrontRequest $request) {
+ $viewer = $this->getViewer();
$e_name = true;
+ $v_name = null;
$errors = array();
+
if ($request->isFormPost()) {
- if (!$object_name) {
+ $v_name = trim($request->getStr('object_name'));
+ if (!$v_name) {
$e_name = pht('Required');
$errors[] = pht('An object name is required.');
}
@@ -17,66 +79,18 @@
if (!$errors) {
$object = id(new PhabricatorObjectQuery())
->setViewer($viewer)
- ->withNames(array($object_name))
+ ->withNames(array($v_name))
->executeOne();
if (!$object) {
$e_name = pht('Invalid');
$errors[] = pht('No object exists with that name.');
}
+ }
- if (!$errors) {
-
- // TODO: Let the adapters claim objects instead.
-
- if ($object instanceof DifferentialRevision) {
- $adapter = HeraldDifferentialRevisionAdapter::newLegacyAdapter(
- $object,
- $object->loadActiveDiff());
- } else if ($object instanceof PhabricatorRepositoryCommit) {
- $adapter = id(new HeraldCommitAdapter())
- ->setCommit($object);
- } else if ($object instanceof ManiphestTask) {
- $adapter = id(new HeraldManiphestTaskAdapter())
- ->setTask($object);
- } else if ($object instanceof PholioMock) {
- $adapter = id(new HeraldPholioMockAdapter())
- ->setMock($object);
- } else if ($object instanceof PhrictionDocument) {
- $adapter = id(new PhrictionDocumentHeraldAdapter())
- ->setDocument($object);
- } else if ($object instanceof PonderQuestion) {
- $adapter = id(new HeraldPonderQuestionAdapter())
- ->setQuestion($object);
- } else if ($object instanceof PhabricatorMetaMTAMail) {
- $adapter = id(new PhabricatorMailOutboundMailHeraldAdapter())
- ->setObject($object);
- } else {
- throw new Exception(pht('Can not build adapter for object!'));
- }
-
- $adapter->setIsNewObject(false);
-
- $rules = id(new HeraldRuleQuery())
- ->setViewer($viewer)
- ->withContentTypes(array($adapter->getAdapterContentType()))
- ->withDisabled(false)
- ->needConditionsAndActions(true)
- ->needAppliedToPHIDs(array($object->getPHID()))
- ->needValidateAuthors(true)
- ->execute();
-
- $engine = id(new HeraldEngine())
- ->setDryRun(true);
-
- $effects = $engine->applyRules($rules, $adapter);
- $engine->applyEffects($effects, $adapter, $rules);
-
- $xscript = $engine->getTranscript();
-
- return id(new AphrontRedirectResponse())
- ->setURI('/herald/transcript/'.$xscript->getID().'/');
- }
+ if (!$errors) {
+ $this->setTestObject($object);
+ return null;
}
}
@@ -92,11 +106,89 @@
->setLabel(pht('Object Name'))
->setName('object_name')
->setError($e_name)
- ->setValue($object_name))
+ ->setValue($v_name))
->appendChild(
id(new AphrontFormSubmitControl())
- ->setValue(pht('Test Rules')));
+ ->setValue(pht('Continue')));
+ return $this->buildTestConsoleResponse($form, $errors);
+ }
+
+ private function loadAdapter(AphrontRequest $request) {
+ $viewer = $this->getViewer();
+ $object = $this->getTestObject();
+
+ $adapter_key = $request->getStr('adapter');
+
+ $adapters = HeraldAdapter::getAllAdapters();
+
+ $can_select = array();
+ $display_adapters = array();
+ foreach ($adapters as $key => $adapter) {
+ if (!$adapter->isTestAdapterForObject($object)) {
+ continue;
+ }
+
+ if (!$adapter->isAvailableToUser($viewer)) {
+ continue;
+ }
+
+ $display_adapters[$key] = $adapter;
+
+ if ($adapter->canCreateTestAdapterForObject($object)) {
+ $can_select[$key] = $adapter;
+ }
+ }
+
+ if ($request->isFormPost() && $adapter_key) {
+ if (isset($can_select[$adapter_key])) {
+ $adapter = $can_select[$adapter_key]->newTestAdapter($object);
+ $this->setTestAdapter($adapter);
+ return null;
+ }
+ }
+
+ $form = id(new AphrontFormView())
+ ->addHiddenInput('object_name', $request->getStr('object_name'))
+ ->setViewer($viewer);
+
+ $cancel_uri = $this->getApplicationURI();
+
+ if (!$display_adapters) {
+ $form
+ ->appendRemarkupInstructions(
+ pht('//There are no available Herald events for this object.//'))
+ ->appendControl(
+ id(new AphrontFormSubmitControl())
+ ->addCancelButton($cancel_uri));
+ } else {
+ $adapter_control = id(new AphrontFormRadioButtonControl())
+ ->setLabel(pht('Event'))
+ ->setName('adapter')
+ ->setValue(head_key($can_select));
+
+ foreach ($display_adapters as $adapter_key => $adapter) {
+ $is_disabled = empty($can_select[$adapter_key]);
+
+ $adapter_control->addButton(
+ $adapter_key,
+ $adapter->getAdapterContentName(),
+ $adapter->getAdapterTestDescription(),
+ null,
+ $is_disabled);
+ }
+
+ $form
+ ->appendControl($adapter_control)
+ ->appendControl(
+ id(new AphrontFormSubmitControl())
+ ->setValue(pht('Run Test')));
+ }
+
+ return $this->buildTestConsoleResponse($form, array());
+ }
+
+ private function buildTestConsoleResponse($form, array $errors) {
$box = id(new PHUIObjectBoxView())
->setFormErrors($errors)
->setForm($form);
@@ -118,11 +210,7 @@
return $this->newPage()
->setTitle($title)
->setCrumbs($crumbs)
- ->appendChild(
- array(
- $view,
- ));
-
+ ->appendChild($view);
}
}
diff --git a/src/applications/maniphest/herald/HeraldManiphestTaskAdapter.php b/src/applications/maniphest/herald/HeraldManiphestTaskAdapter.php
--- a/src/applications/maniphest/herald/HeraldManiphestTaskAdapter.php
+++ b/src/applications/maniphest/herald/HeraldManiphestTaskAdapter.php
@@ -16,6 +16,15 @@
return pht('React to tasks being created or updated.');
}
+ public function isTestAdapterForObject($object) {
+ return ($object instanceof ManiphestTask);
+ }
+
+ public function getAdapterTestDescription() {
+ return pht(
+ 'Test rules which run when a task is created or updated.');
+ }
+
protected function initializeNewAdapter() {
$this->task = $this->newObject();
}
@@ -46,10 +55,16 @@
$this->task = $task;
return $this;
}
+
public function getTask() {
return $this->task;
}
+ public function setObject($object) {
+ $this->task = $object;
+ return $this;
+ }
+
public function getObject() {
return $this->task;
}
diff --git a/src/applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php b/src/applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php
--- a/src/applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php
+++ b/src/applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php
@@ -21,6 +21,17 @@
return new PhabricatorMetaMTAMail();
}
+ public function isTestAdapterForObject($object) {
+ return ($object instanceof PhabricatorMetaMTAMail);
+ }
+
+ public function getAdapterTestDescription() {
+ return pht(
+ 'Test rules which run when outbound mail is being prepared for '.
+ 'delivery.');
+ }
+
+
public function getObject() {
return $this->mail;
}
diff --git a/src/applications/pholio/herald/HeraldPholioMockAdapter.php b/src/applications/pholio/herald/HeraldPholioMockAdapter.php
--- a/src/applications/pholio/herald/HeraldPholioMockAdapter.php
+++ b/src/applications/pholio/herald/HeraldPholioMockAdapter.php
@@ -20,6 +20,20 @@
return new PholioMock();
}
+ public function isTestAdapterForObject($object) {
+ return ($object instanceof PholioMock);
+ }
+
+ public function getAdapterTestDescription() {
+ return pht(
+ 'Test rules which run when a mock is created or updated.');
+ }
+
+ public function setObject($object) {
+ $this->mock = $object;
+ return $this;
+ }
+
public function getObject() {
return $this->mock;
}
@@ -28,6 +42,7 @@
$this->mock = $mock;
return $this;
}
+
public function getMock() {
return $this->mock;
}
diff --git a/src/applications/phriction/herald/PhrictionDocumentHeraldAdapter.php b/src/applications/phriction/herald/PhrictionDocumentHeraldAdapter.php
--- a/src/applications/phriction/herald/PhrictionDocumentHeraldAdapter.php
+++ b/src/applications/phriction/herald/PhrictionDocumentHeraldAdapter.php
@@ -20,6 +20,20 @@
return new PhrictionDocument();
}
+ public function isTestAdapterForObject($object) {
+ return ($object instanceof PhrictionDocument);
+ }
+
+ public function getAdapterTestDescription() {
+ return pht(
+ 'Test rules which run when a wiki document is created or updated.');
+ }
+
+ public function setObject($object) {
+ $this->document = $object;
+ return $this;
+ }
+
public function getObject() {
return $this->document;
}
diff --git a/src/applications/ponder/herald/HeraldPonderQuestionAdapter.php b/src/applications/ponder/herald/HeraldPonderQuestionAdapter.php
--- a/src/applications/ponder/herald/HeraldPonderQuestionAdapter.php
+++ b/src/applications/ponder/herald/HeraldPonderQuestionAdapter.php
@@ -20,6 +20,21 @@
$this->question = $this->newObject();
}
+
+ public function isTestAdapterForObject($object) {
+ return ($object instanceof PonderQuestion);
+ }
+
+ public function getAdapterTestDescription() {
+ return pht(
+ 'Test rules which run when a question is created or updated.');
+ }
+
+ public function setObject($object) {
+ $this->question = $object;
+ return $this;
+ }
+
public function supportsApplicationEmail() {
return true;
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Mar 18, 3:23 PM (1 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7440572
Default Alt Text
D16360.diff (15 KB)
Attached To
Mode
D16360: Make Herald test workflow modular and more clear
Attached
Detach File
Event Timeline
Log In to Comment