From bd2eaad04f035a5f1ccf014fd22b51c63d3b098b Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 18 Mar 2015 07:09:43 -0700 Subject: [PATCH] Add "phabricator.silent" for stopping all outbound events from an install Summary: Ref T7522. This is mostly useful in the cluster, but could be useful for external installs too. If you want to import an instance into a test/dry-run state (in the cluster, to test an import; in the general case, to do something like test new hardware or configuration), you currently risk spamming users with a lot of duplicate notifications. In particular, if Phabricator tracks remotes, both instances will continue importing commits and sending email about them. Both instances will try to publish to mirrors, too, which could be bad news, and both instances will try to update linked services. Instead, provide a flag to let an instance run in "silent mode", which disables all outbound messaging and data. We need to remember to support this flag on any new outbound channels, but we add about one of those per year so I think that's reasonable. Test Plan: - Flipped config. - Saw it void email, feed and mirroring. - Didn't test SMS since it's not really in use yet and not convenient to test. - (Can you think of any publishing I missed?) Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T7522 Differential Revision: https://secure.phabricator.com/D12109 --- .../option/PhabricatorCoreConfigOptions.php | 35 +++++++++++++++---- .../DiffusionRepositoryEditMainController.php | 8 +++++ .../worker/DoorkeeperFeedWorker.php | 5 +++ .../feed/worker/FeedPublisherHTTPWorker.php | 5 +++ .../storage/PhabricatorMetaMTAMail.php | 9 +++++ .../PhabricatorRepositoryMirrorEngine.php | 6 ++++ .../sms/worker/PhabricatorSMSSendWorker.php | 9 +++++ .../testing/PhabricatorTestCase.php | 3 ++ 8 files changed, 74 insertions(+), 6 deletions(-) diff --git a/src/applications/config/option/PhabricatorCoreConfigOptions.php b/src/applications/config/option/PhabricatorCoreConfigOptions.php index 8d6e4b30f9..2521e58f9c 100644 --- a/src/applications/config/option/PhabricatorCoreConfigOptions.php +++ b/src/applications/config/option/PhabricatorCoreConfigOptions.php @@ -214,12 +214,35 @@ final class PhabricatorCoreConfigOptions ->setDescription(pht('Cache namespace.')), $this->newOption('phabricator.allow-email-users', 'bool', false) ->setBoolOptions( - array( - pht('Allow'), - pht('Disallow'), - ))->setDescription( - pht( - 'Allow non-members to interact with tasks over email.')), + array( + pht('Allow'), + pht('Disallow'), + )) + ->setDescription( + pht('Allow non-members to interact with tasks over email.')), + $this->newOption('phabricator.silent', 'bool', false) + ->setLocked(true) + ->setBoolOptions( + array( + pht('Run Silently'), + pht('Run Normally'), + )) + ->setSummary(pht('Stop Phabricator from sending any email, etc.')) + ->setDescription( + pht( + 'This option allows you to stop Phabricator from sending '. + 'any data to external services. Among other things, it will '. + 'disable email, SMS, repository mirroring, and HTTP hooks.'. + "\n\n". + 'This option is intended to allow a Phabricator instance to '. + 'be exported, copied, imported, and run in a test environment '. + 'without impacting users. For example, if you are migrating '. + 'to new hardware, you could perform a test migration first, '. + 'make sure things work, and then do a production cutover '. + 'later with higher confidence and less disruption. Without '. + 'this flag, users would receive duplicate email during the '. + 'time the test instance and old production instance were '. + 'both in operation.')), ); } diff --git a/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php b/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php index de72ce394b..0b270998f0 100644 --- a/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php +++ b/src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php @@ -126,7 +126,15 @@ final class DiffusionRepositoryEditMainController $boxes[] = id(new PhabricatorAnchorView())->setAnchorName('mirrors'); + $mirror_info = array(); + if (PhabricatorEnv::getEnvConfig('phabricator.silent')) { + $mirror_info[] = pht( + 'Phabricator is running in silent mode, so changes will not '. + 'be pushed to mirrors.'); + } + $boxes[] = id(new PHUIObjectBoxView()) + ->setFormErrors($mirror_info) ->setHeaderText(pht('Mirrors')) ->addPropertyList($mirror_properties); diff --git a/src/applications/doorkeeper/worker/DoorkeeperFeedWorker.php b/src/applications/doorkeeper/worker/DoorkeeperFeedWorker.php index f73451ee87..a280e85fbb 100644 --- a/src/applications/doorkeeper/worker/DoorkeeperFeedWorker.php +++ b/src/applications/doorkeeper/worker/DoorkeeperFeedWorker.php @@ -157,6 +157,11 @@ abstract class DoorkeeperFeedWorker extends FeedPushWorker { * @{method:publishFeedStory}. */ final protected function doWork() { + if (PhabricatorEnv::getEnvConfig('phabricator.silent')) { + $this->log(pht('Phabricator is running in silent mode.')); + return; + } + if (!$this->isEnabled()) { $this->log("Doorkeeper worker '%s' is not enabled.\n", get_class($this)); return; diff --git a/src/applications/feed/worker/FeedPublisherHTTPWorker.php b/src/applications/feed/worker/FeedPublisherHTTPWorker.php index e4e0600cb1..4742e52a29 100644 --- a/src/applications/feed/worker/FeedPublisherHTTPWorker.php +++ b/src/applications/feed/worker/FeedPublisherHTTPWorker.php @@ -3,6 +3,11 @@ final class FeedPublisherHTTPWorker extends FeedPushWorker { protected function doWork() { + if (PhabricatorEnv::getEnvConfig('phabricator.silent')) { + // Don't invoke hooks in silent mode. + return; + } + $story = $this->loadFeedStory(); $data = $story->getStoryData(); diff --git a/src/applications/metamta/storage/PhabricatorMetaMTAMail.php b/src/applications/metamta/storage/PhabricatorMetaMTAMail.php index e6d8e52c45..0fb118252a 100644 --- a/src/applications/metamta/storage/PhabricatorMetaMTAMail.php +++ b/src/applications/metamta/storage/PhabricatorMetaMTAMail.php @@ -633,6 +633,15 @@ final class PhabricatorMetaMTAMail extends PhabricatorMetaMTADAO { } } + if (PhabricatorEnv::getEnvConfig('phabricator.silent')) { + $this->setStatus(self::STATUS_VOID); + $this->setMessage( + pht( + 'Phabricator is running in silent mode. See `phabricator.silent` '. + 'in the configuration to change this setting.')); + return $this->save(); + } + $mailer->addHeader('X-Phabricator-Sent-This-Message', 'Yes'); $mailer->addHeader('X-Mail-Transport-Agent', 'MetaMTA'); diff --git a/src/applications/repository/engine/PhabricatorRepositoryMirrorEngine.php b/src/applications/repository/engine/PhabricatorRepositoryMirrorEngine.php index d73b2bed0f..8d3dd9f8f9 100644 --- a/src/applications/repository/engine/PhabricatorRepositoryMirrorEngine.php +++ b/src/applications/repository/engine/PhabricatorRepositoryMirrorEngine.php @@ -13,6 +13,12 @@ final class PhabricatorRepositoryMirrorEngine return; } + if (PhabricatorEnv::getEnvConfig('phabricator.silent')) { + $this->log( + pht('Phabricator is running in silent mode; declining to mirror.')); + return; + } + $mirrors = id(new PhabricatorRepositoryMirrorQuery()) ->setViewer($this->getViewer()) ->withRepositoryPHIDs(array($repository->getPHID())) diff --git a/src/infrastructure/sms/worker/PhabricatorSMSSendWorker.php b/src/infrastructure/sms/worker/PhabricatorSMSSendWorker.php index fa56336809..0ee9aebb77 100644 --- a/src/infrastructure/sms/worker/PhabricatorSMSSendWorker.php +++ b/src/infrastructure/sms/worker/PhabricatorSMSSendWorker.php @@ -55,6 +55,15 @@ final class PhabricatorSMSSendWorker // give the provider name the same treatment as phone number $sms->setProviderShortName($adapter->getProviderShortName()); + if (PhabricatorEnv::getEnvConfig('phabricator.silent')) { + $sms->setSendStatus(PhabricatorSMS::STATUS_FAILED_PERMANENTLY); + $sms->save(); + throw new PhabricatorWorkerPermanentFailureException( + pht( + 'Phabricator is running in silent mode. See `phabricator.silent` '. + 'in the configuration to change this setting.')); + } + try { $result = $adapter->send(); list($sms_id, $sent_status) = $adapter->getSMSDataFromResult($result); diff --git a/src/infrastructure/testing/PhabricatorTestCase.php b/src/infrastructure/testing/PhabricatorTestCase.php index 53950ddf73..2a2834c93f 100644 --- a/src/infrastructure/testing/PhabricatorTestCase.php +++ b/src/infrastructure/testing/PhabricatorTestCase.php @@ -119,6 +119,9 @@ abstract class PhabricatorTestCase extends ArcanistPhutilTestCase { $this->env->overrideEnvConfig( 'phabricator.base-uri', 'http://phabricator.example.com'); + + // Tests do their own stubbing/voiding for events. + $this->env->overrideEnvConfig('phabricator.silent', false); } protected function didRunTests() {