mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-22 14:52:41 +01:00
Add an example event listener, improve documentation, and add a commit discovery event
Summary: Improve documentation around Phabricator events. Test Plan: Generated and read documentation. Ran test script. Reviewers: btrahan, jungejason Reviewed By: jungejason CC: aran Maniphest Tasks: T1092 Differential Revision: https://secure.phabricator.com/D2917
This commit is contained in:
parent
61b79b5359
commit
ddf67fce58
8 changed files with 322 additions and 10 deletions
57
scripts/util/emit_test_event.php
Executable file
57
scripts/util/emit_test_event.php
Executable file
|
@ -0,0 +1,57 @@
|
||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$root = dirname(dirname(dirname(__FILE__)));
|
||||||
|
require_once $root.'/scripts/__init_script__.php';
|
||||||
|
|
||||||
|
$args = new PhutilArgumentParser($argv);
|
||||||
|
$args->setTagline('emit a test event');
|
||||||
|
$args->setSynopsis(<<<EOHELP
|
||||||
|
**emit_test_event.php** [--listen listener] ...
|
||||||
|
Emit a test event after installing any specified __listener__s.
|
||||||
|
EOHELP
|
||||||
|
);
|
||||||
|
$args->parseStandardArguments();
|
||||||
|
$args->parse(
|
||||||
|
array(
|
||||||
|
array(
|
||||||
|
'name' => 'listen',
|
||||||
|
'param' => 'listener',
|
||||||
|
'repeat' => true,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
$console = PhutilConsole::getConsole();
|
||||||
|
foreach ($args->getArg('listen') as $listener) {
|
||||||
|
$console->writeOut("Installing '%s'...\n", $listener);
|
||||||
|
newv($listener, array())->register();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$console->writeOut("Emitting event...\n");
|
||||||
|
|
||||||
|
PhutilEventEngine::dispatchEvent(
|
||||||
|
new PhabricatorEvent(
|
||||||
|
PhabricatorEventType::TYPE_TEST_DIDRUNTEST,
|
||||||
|
array(
|
||||||
|
'time' => time(),
|
||||||
|
)));
|
||||||
|
|
||||||
|
$console->writeOut("Done.\n");
|
||||||
|
exit(0);
|
|
@ -632,6 +632,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorEvent' => 'infrastructure/events/PhabricatorEvent.php',
|
'PhabricatorEvent' => 'infrastructure/events/PhabricatorEvent.php',
|
||||||
'PhabricatorEventEngine' => 'infrastructure/events/PhabricatorEventEngine.php',
|
'PhabricatorEventEngine' => 'infrastructure/events/PhabricatorEventEngine.php',
|
||||||
'PhabricatorEventType' => 'infrastructure/events/constant/PhabricatorEventType.php',
|
'PhabricatorEventType' => 'infrastructure/events/constant/PhabricatorEventType.php',
|
||||||
|
'PhabricatorExampleEventListener' => 'infrastructure/events/PhabricatorExampleEventListener.php',
|
||||||
'PhabricatorFeedBuilder' => 'applications/feed/builder/PhabricatorFeedBuilder.php',
|
'PhabricatorFeedBuilder' => 'applications/feed/builder/PhabricatorFeedBuilder.php',
|
||||||
'PhabricatorFeedConstants' => 'applications/feed/constants/PhabricatorFeedConstants.php',
|
'PhabricatorFeedConstants' => 'applications/feed/constants/PhabricatorFeedConstants.php',
|
||||||
'PhabricatorFeedController' => 'applications/feed/controller/PhabricatorFeedController.php',
|
'PhabricatorFeedController' => 'applications/feed/controller/PhabricatorFeedController.php',
|
||||||
|
@ -1647,9 +1648,12 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorErrorExample' => 'PhabricatorUIExample',
|
'PhabricatorErrorExample' => 'PhabricatorUIExample',
|
||||||
'PhabricatorEvent' => 'PhutilEvent',
|
'PhabricatorEvent' => 'PhutilEvent',
|
||||||
'PhabricatorEventType' => 'PhutilEventType',
|
'PhabricatorEventType' => 'PhutilEventType',
|
||||||
|
'PhabricatorExampleEventListener' => 'PhutilEventListener',
|
||||||
'PhabricatorFeedController' => 'PhabricatorController',
|
'PhabricatorFeedController' => 'PhabricatorController',
|
||||||
'PhabricatorFeedDAO' => 'PhabricatorLiskDAO',
|
'PhabricatorFeedDAO' => 'PhabricatorLiskDAO',
|
||||||
'PhabricatorFeedPublicStreamController' => 'PhabricatorFeedController',
|
'PhabricatorFeedPublicStreamController' => 'PhabricatorFeedController',
|
||||||
|
'PhabricatorFeedQuery' => 'PhabricatorIDPagedPolicyQuery',
|
||||||
|
'PhabricatorFeedStory' => 'PhabricatorPolicyInterface',
|
||||||
'PhabricatorFeedStoryAggregate' => 'PhabricatorFeedStory',
|
'PhabricatorFeedStoryAggregate' => 'PhabricatorFeedStory',
|
||||||
'PhabricatorFeedStoryAudit' => 'PhabricatorFeedStory',
|
'PhabricatorFeedStoryAudit' => 'PhabricatorFeedStory',
|
||||||
'PhabricatorFeedStoryCommit' => 'PhabricatorFeedStory',
|
'PhabricatorFeedStoryCommit' => 'PhabricatorFeedStory',
|
||||||
|
|
|
@ -374,6 +374,15 @@ final class PhabricatorRepositoryPullLocalDaemon
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->setCache($repository, $commit_identifier);
|
$this->setCache($repository, $commit_identifier);
|
||||||
|
|
||||||
|
PhutilEventEngine::dispatchEvent(
|
||||||
|
new PhabricatorEvent(
|
||||||
|
PhabricatorEventType::TYPE_DIFFUSION_DIDDISCOVERCOMMIT,
|
||||||
|
array(
|
||||||
|
'repository' => $repository,
|
||||||
|
'commit' => $commit,
|
||||||
|
)));
|
||||||
|
|
||||||
} catch (AphrontQueryDuplicateKeyException $ex) {
|
} catch (AphrontQueryDuplicateKeyException $ex) {
|
||||||
$commit->killTransaction();
|
$commit->killTransaction();
|
||||||
// Ignore. This can happen because we discover the same new commit
|
// Ignore. This can happen because we discover the same new commit
|
||||||
|
|
|
@ -9,12 +9,68 @@ Phabricator allows you to install custom runtime event listeners which can react
|
||||||
to certain things happening (like a Maniphest Task being edited) and run custom
|
to certain things happening (like a Maniphest Task being edited) and run custom
|
||||||
code to perform logging, synchronize with other systems, or modify workflows.
|
code to perform logging, synchronize with other systems, or modify workflows.
|
||||||
|
|
||||||
NOTE: This feature is new and experimental, so few events are available and
|
These listeners are PHP classes which you install beside Phabricator, and which
|
||||||
things might not be completely stable.
|
Phabricator loads at runtime and runs in-process. They are the most direct and
|
||||||
|
powerful way to respond to events.
|
||||||
|
|
||||||
|
= Installing Event Listeners =
|
||||||
|
|
||||||
|
To install event listeners, follow these steps:
|
||||||
|
|
||||||
|
- Write a listener class which extends @{class:PhutilEventListener}.
|
||||||
|
- Add it to a libphutil library, or create a new library (for instructions,
|
||||||
|
see @{article:libphutil Libraries User Guide}.
|
||||||
|
- Configure Phabricator to load the library by adding it to `load-libraries`
|
||||||
|
in the Phabricator config.
|
||||||
|
- Configure Phabricator to install the event listener by adding the class
|
||||||
|
name to `events.listeners` in the Phabricator config.
|
||||||
|
|
||||||
|
You can verify your listener is registered in the "Events" tab of DarkConsole.
|
||||||
|
It should appear at the top under "Registered Event Listeners". You can also
|
||||||
|
see any events the page emitted there. For details on DarkConsole, see
|
||||||
|
@{article:Using DarkConsole}.
|
||||||
|
|
||||||
|
= Example Listener =
|
||||||
|
|
||||||
|
Phabricator includes an example event listener,
|
||||||
|
@{class:PhabricatorExampleEventListener}, which may be useful as a starting
|
||||||
|
point in developing your own listeners. This listener listens for a test
|
||||||
|
event that is emitted by the script `scripts/util/emit_test_event.php`.
|
||||||
|
|
||||||
|
If you run this script normally, it should output something like this:
|
||||||
|
|
||||||
|
$ ./scripts/util/emit_test_event.php
|
||||||
|
Emitting event...
|
||||||
|
Done.
|
||||||
|
|
||||||
|
This is because there are no listeners for the event, so nothing reacts to it
|
||||||
|
when it is emitted. You can add the example listener by either adding it to
|
||||||
|
your `events.listeners` configuration or with the `--listen` command-line flag:
|
||||||
|
|
||||||
|
$ ./scripts/util/emit_test_event.php --listen PhabricatorExampleEventListener
|
||||||
|
Installing 'PhabricatorExampleEventListener'...
|
||||||
|
Emitting event...
|
||||||
|
PhabricatorExampleEventListener got test event at 1341344566
|
||||||
|
Done.
|
||||||
|
|
||||||
|
This time, the listener was installed and had its callback invoked when the
|
||||||
|
test event was emitted.
|
||||||
|
|
||||||
= Available Events =
|
= Available Events =
|
||||||
|
|
||||||
== PhabricatorEventType::TYPE_MANIPHEST_WILLEDITTASK ==
|
You can find a list of all Phabricator events in @{class:PhabricatorEventType}.
|
||||||
|
|
||||||
|
== All Events ==
|
||||||
|
|
||||||
|
The special constant `PhutilEventType::TYPE_ALL` will let you listen for all
|
||||||
|
events. Normally, you want to listen only to specific events, but if you're
|
||||||
|
writing a generic handler you can listen to all events with this constant
|
||||||
|
rather than by enumerating each event.
|
||||||
|
|
||||||
|
== Maniphest: Will Edit Task ==
|
||||||
|
|
||||||
|
The constant for this event is
|
||||||
|
`PhabricatorEventType::TYPE_MANIPHEST_WILLEDITTASK`.
|
||||||
|
|
||||||
This event is dispatched before a task is edited, and allows you to respond to
|
This event is dispatched before a task is edited, and allows you to respond to
|
||||||
or alter the edit. Data available on this event:
|
or alter the edit. Data available on this event:
|
||||||
|
@ -26,14 +82,41 @@ or alter the edit. Data available on this event:
|
||||||
- ##mail## If this edit originates from email, the
|
- ##mail## If this edit originates from email, the
|
||||||
@{class:PhabricatorMetaMTAReceivedMail} object.
|
@{class:PhabricatorMetaMTAReceivedMail} object.
|
||||||
|
|
||||||
== PhabricatorEventType::TYPE_DIFFERENTIAL_WILLSENDMAIL ==
|
This is similar to the next event (did edit task) but occurs before the edit
|
||||||
|
begins.
|
||||||
|
|
||||||
|
== Maniphest: Did Edit Task ==
|
||||||
|
|
||||||
|
The constant for this event is
|
||||||
|
`PhabricatorEventType::TYPE_MANIPHEST_DIDEDITTASK`.
|
||||||
|
|
||||||
|
This event is dispatched after a task is edited, and allows you to react to the
|
||||||
|
edit. Data available on this event:
|
||||||
|
|
||||||
|
- ##task## The @{class:ManiphestTask} that was edited.
|
||||||
|
- ##transactions## The list of edits (objects of class
|
||||||
|
@{class:ManiphestTransaction}) that were applied.
|
||||||
|
- ##new## A boolean indicating if this task was newly created.
|
||||||
|
- ##mail## If this edit originates from email, the
|
||||||
|
@{class:PhabricatorMetaMTAReceivedMail} object.
|
||||||
|
|
||||||
|
This is similar to the previous event (will edit task) but occurs after the
|
||||||
|
edit completes.
|
||||||
|
|
||||||
|
== Differential: Will Send Mail ==
|
||||||
|
|
||||||
|
The constant for this event is
|
||||||
|
`PhabricatorEventType::TYPE_DIFFERENTIAL_WILLSENDMAIL`
|
||||||
|
|
||||||
This event is dispatched before Differential sends an email, and allows you to
|
This event is dispatched before Differential sends an email, and allows you to
|
||||||
edit the message that will be sent. Data available on this event:
|
edit the message that will be sent. Data available on this event:
|
||||||
|
|
||||||
- ##mail## The @{class:PhabricatorMetaMTAMail} being edited.
|
- ##mail## The @{class:PhabricatorMetaMTAMail} being edited.
|
||||||
|
|
||||||
== PhabricatorEventType::TYPE_DIFFERENTIAL_WILLMARKGENERATED ==
|
== Differential: Will Mark Generated ==
|
||||||
|
|
||||||
|
The constant for this event is
|
||||||
|
`PhabricatorEventType::TYPE_DIFFERENTIAL_WILLMARKGENERATED`.
|
||||||
|
|
||||||
This event is dispatched before Differential decides if a file is generated (and
|
This event is dispatched before Differential decides if a file is generated (and
|
||||||
doesn't need to be reviewed) or not. Data available on this event:
|
doesn't need to be reviewed) or not. Data available on this event:
|
||||||
|
@ -41,3 +124,92 @@ doesn't need to be reviewed) or not. Data available on this event:
|
||||||
- ##corpus## Body of the file.
|
- ##corpus## Body of the file.
|
||||||
- ##is_generated## Boolean indicating if this file should be treated as
|
- ##is_generated## Boolean indicating if this file should be treated as
|
||||||
generated.
|
generated.
|
||||||
|
|
||||||
|
== Diffusion: Did Discover Commit ==
|
||||||
|
|
||||||
|
The constant for this event is
|
||||||
|
`PhabricatorEventType::TYPE_DIFFUSION_DIDDISCOVERCOMMIT`.
|
||||||
|
|
||||||
|
This event is dispatched when the daemons discover a commit for the first time.
|
||||||
|
This event happens very early in the pipeline, and not all commit information
|
||||||
|
will be available yet. Data available on this event:
|
||||||
|
|
||||||
|
- `commit` The @{class:PhabricatorRepositoryCommit} that was discovered.
|
||||||
|
- `repository` The @{class:PhabricatorRepository} the commit was discovered
|
||||||
|
in.
|
||||||
|
|
||||||
|
== Edge: Will Edit Edges ==
|
||||||
|
|
||||||
|
NOTE: Edge events are low-level events deep in the core. It is more difficult to
|
||||||
|
correct implement listeners for these events than for higher-level events.
|
||||||
|
|
||||||
|
The constant for this event is
|
||||||
|
`PhabricatorEventType::TYPE_EDGE_WILLEDITEDGES`.
|
||||||
|
|
||||||
|
This event is dispatched before @{class:PhabricatorEdgeEditor} makes an edge
|
||||||
|
edit.
|
||||||
|
|
||||||
|
- `id` An identifier for this edit operation.
|
||||||
|
- `add` A list of dictionaries, each representing a new edge.
|
||||||
|
- `rem` A list of dictionaries, each representing a removed edge.
|
||||||
|
|
||||||
|
This is similar to the next event (did edit edges) but occurs before the
|
||||||
|
edit begins.
|
||||||
|
|
||||||
|
== Edge: Did Edit Edges ==
|
||||||
|
|
||||||
|
The constant for this event is
|
||||||
|
`PhabricatorEventType::TYPE_EDGE_DIDEDITEDGES`.
|
||||||
|
|
||||||
|
This event is dispatched after @{class:PhabricatorEdgeEditor} makes an edge
|
||||||
|
edit, but before it commits the transactions. Data available on this event:
|
||||||
|
|
||||||
|
- `id` An identifier for this edit operation. This is the same ID as
|
||||||
|
the one included in the corresponding "will edit edges" event.
|
||||||
|
- `add` A list of dictionaries, each representing a new edge.
|
||||||
|
- `rem` A list of dictionaries, each representing a removed edge.
|
||||||
|
|
||||||
|
This is similar to the previous event (will edit edges) but occurs after the
|
||||||
|
edit completes.
|
||||||
|
|
||||||
|
== Test: Did Run Test ==
|
||||||
|
|
||||||
|
The constant for this event is
|
||||||
|
`PhabricatorEventType::TYPE_TEST_DIDRUNTEST`.
|
||||||
|
|
||||||
|
This is a test event for testing event listeners. See above for details.
|
||||||
|
|
||||||
|
= Debugging Listeners =
|
||||||
|
|
||||||
|
If you're having problems with your listener, try these steps:
|
||||||
|
|
||||||
|
- If you're getting an error about Phabricator being unable to find the
|
||||||
|
listener class, make sure you've added it to a libphutil library and
|
||||||
|
configured Phabricator to load the library with `load-libraries`.
|
||||||
|
- Make sure the listener is registered. It should appear in the "Events" tab
|
||||||
|
of DarkConsole. If it's not there, you may have forgotten to add it to
|
||||||
|
`events.listeners`.
|
||||||
|
- Make sure it calls `listen()` on the right events in its `register()`
|
||||||
|
method. If you don't listen for the events you're interested in, you
|
||||||
|
won't get a callback.
|
||||||
|
- Make sure the events you're listening for are actually happening. If they
|
||||||
|
occur on a normal page they should appear in the "Events" tab of
|
||||||
|
DarkConsole. If they occur on a POST, you could add a `phlog()`
|
||||||
|
to the source code near the event and check your error log to make sure the
|
||||||
|
code ran.
|
||||||
|
- You can check if your callback is getting invoked by adding `phlog()` with
|
||||||
|
a message and checking the error log.
|
||||||
|
- You can try listening to `PhutilEventType::TYPE_ALL` instead of a specific
|
||||||
|
event type to get all events, to narrow down whether problems are caused
|
||||||
|
by the types of events you're listening to.
|
||||||
|
- You can edit the `emit_test_event.php` script to emit other types of
|
||||||
|
events instead, to test that your listener reacts to them properly. You
|
||||||
|
might have to use fake data, but this gives you an easy way to test the
|
||||||
|
at least the basics.
|
||||||
|
|
||||||
|
= Next Steps =
|
||||||
|
|
||||||
|
Continue by:
|
||||||
|
|
||||||
|
- taking a look at @{class:PhabricatorExampleEventListener}; or
|
||||||
|
- building a library with @{article:@{article:libphutil Libraries User Guide}.
|
|
@ -16,6 +16,10 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group events
|
||||||
|
*/
|
||||||
final class PhabricatorEvent extends PhutilEvent {
|
final class PhabricatorEvent extends PhutilEvent {
|
||||||
|
|
||||||
private $user;
|
private $user;
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group events
|
||||||
|
*/
|
||||||
final class PhabricatorEventEngine {
|
final class PhabricatorEventEngine {
|
||||||
|
|
||||||
public static function initialize() {
|
public static function initialize() {
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example event listener. For details about installing Phabricator event hooks,
|
||||||
|
* refer to @{article:Events User Guide: Installing Event Listeners}.
|
||||||
|
*
|
||||||
|
* @group events
|
||||||
|
*/
|
||||||
|
final class PhabricatorExampleEventListener extends PhutilEventListener {
|
||||||
|
|
||||||
|
public function register() {
|
||||||
|
// When your listener is installed, its register() method will be called.
|
||||||
|
// You should listen() to any events you are interested in here.
|
||||||
|
|
||||||
|
$this->listen(PhabricatorEventType::TYPE_TEST_DIDRUNTEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleEvent(PhutilEvent $event) {
|
||||||
|
// When an event you have called listen() for in your register() method
|
||||||
|
// occurs, this method will be invoked. You should respond to the event.
|
||||||
|
|
||||||
|
// In this case, we just echo a message out so the event test script will
|
||||||
|
// do something visible.
|
||||||
|
|
||||||
|
$console = PhutilConsole::getConsole();
|
||||||
|
$console->writeOut(
|
||||||
|
"PhabricatorExampleEventListener got test event at %d\n",
|
||||||
|
$event->getValue('time'));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,14 +16,25 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For detailed explanations of these events, see
|
||||||
|
* @{article:Events User Guide: Installing Event Listeners}.
|
||||||
|
*
|
||||||
|
* @group events
|
||||||
|
*/
|
||||||
final class PhabricatorEventType extends PhutilEventType {
|
final class PhabricatorEventType extends PhutilEventType {
|
||||||
|
|
||||||
const TYPE_MANIPHEST_WILLEDITTASK = 'maniphest.willEditTask';
|
const TYPE_MANIPHEST_WILLEDITTASK = 'maniphest.willEditTask';
|
||||||
const TYPE_MANIPHEST_DIDEDITTASK = 'maniphest.didEditTask';
|
const TYPE_MANIPHEST_DIDEDITTASK = 'maniphest.didEditTask';
|
||||||
const TYPE_DIFFERENTIAL_WILLSENDMAIL = 'differential.willSendMail';
|
|
||||||
|
const TYPE_DIFFERENTIAL_WILLSENDMAIL = 'differential.willSendMail';
|
||||||
const TYPE_DIFFERENTIAL_WILLMARKGENERATED = 'differential.willMarkGenerated';
|
const TYPE_DIFFERENTIAL_WILLMARKGENERATED = 'differential.willMarkGenerated';
|
||||||
|
|
||||||
const TYPE_EDGE_WILLEDITEDGES = 'edge.willEditEdges';
|
const TYPE_DIFFUSION_DIDDISCOVERCOMMIT = 'diffusion.didDiscoverCommit';
|
||||||
const TYPE_EDGE_DIDEDITEDGES = 'edge.didEditEdges';
|
|
||||||
|
const TYPE_EDGE_WILLEDITEDGES = 'edge.willEditEdges';
|
||||||
|
const TYPE_EDGE_DIDEDITEDGES = 'edge.didEditEdges';
|
||||||
|
|
||||||
|
const TYPE_TEST_DIDRUNTEST = 'test.didRunTest';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue