diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2196,6 +2196,7 @@ 'PhabricatorIteratedMD5PasswordHasher' => 'infrastructure/util/password/PhabricatorIteratedMD5PasswordHasher.php', 'PhabricatorIteratedMD5PasswordHasherTestCase' => 'infrastructure/util/password/__tests__/PhabricatorIteratedMD5PasswordHasherTestCase.php', 'PhabricatorJIRAAuthProvider' => 'applications/auth/provider/PhabricatorJIRAAuthProvider.php', + 'PhabricatorJIRAConfigOptions' => 'applications/doorkeeper/option/PhabricatorJIRAConfigOptions.php', 'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/PhabricatorJavelinLinter.php', 'PhabricatorJiraIssueHasObjectEdgeType' => 'applications/doorkeeper/edge/PhabricatorJiraIssueHasObjectEdgeType.php', 'PhabricatorJumpNavHandler' => 'applications/search/engine/PhabricatorJumpNavHandler.php', @@ -6120,6 +6121,7 @@ 'PhabricatorIteratedMD5PasswordHasher' => 'PhabricatorPasswordHasher', 'PhabricatorIteratedMD5PasswordHasherTestCase' => 'PhabricatorTestCase', 'PhabricatorJIRAAuthProvider' => 'PhabricatorOAuth1AuthProvider', + 'PhabricatorJIRAConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorJavelinLinter' => 'ArcanistLinter', 'PhabricatorJiraIssueHasObjectEdgeType' => 'PhabricatorEdgeType', 'PhabricatorJumpNavHandler' => 'Phobject', diff --git a/src/applications/doorkeeper/option/PhabricatorJIRAConfigOptions.php b/src/applications/doorkeeper/option/PhabricatorJIRAConfigOptions.php new file mode 100644 --- /dev/null +++ b/src/applications/doorkeeper/option/PhabricatorJIRAConfigOptions.php @@ -0,0 +1,49 @@ +newOption('jira.post-comment', 'bool', true) + ->setBoolOptions( + array( + pht('Enable commenting'), + pht('Disable commenting'), + )) + ->setSummary(pht('Post comment on JIRA issues when revision updated.')) + ->setDescription( + pht( + 'Each time a revision is updated, Differential can post a comment '. + 'on the linked JIRA issue(s). This can be informative, but can '. + 'also overwhelm users with notifications if they are also '. + 'notified by Phabricator.')), + $this->newOption('jira.post-link', 'bool', true) + ->setBoolOptions( + array( + pht('Enable remote link'), + pht('Disable remote link'), + )) + ->setSummary(pht('On JIRA issues add remote links to revisions.')) + ->setDescription( + pht( + 'JIRA issues can have Remote Links to web artifacts related to '. + 'the given issue. This option adds the revision under "implement '. + 'in" under the Issue Links section of the JIRA ticket.')), + ); + } + +} diff --git a/src/applications/doorkeeper/worker/DoorkeeperJIRAFeedWorker.php b/src/applications/doorkeeper/worker/DoorkeeperJIRAFeedWorker.php --- a/src/applications/doorkeeper/worker/DoorkeeperJIRAFeedWorker.php +++ b/src/applications/doorkeeper/worker/DoorkeeperJIRAFeedWorker.php @@ -60,8 +60,6 @@ return; } - $story_text = $this->renderStoryText(); - $xobjs = mgroup($xobjs, 'getApplicationDomain'); foreach ($xobjs as $domain => $xobj_list) { $accounts = id(new PhabricatorExternalAccountQuery()) @@ -84,13 +82,16 @@ foreach ($xobj_list as $xobj) { foreach ($accounts as $account) { try { - $provider->newJIRAFuture( - $account, - 'rest/api/2/issue/'.$xobj->getObjectID().'/comment', - 'POST', - array( - 'body' => $story_text, - ))->resolveJSON(); + $jira_key = $xobj->getObjectID(); + + if (self::shouldPostComment()) { + $this->postComment($account, $jira_key); + } + + if (self::shouldPostLink()) { + $this->postLink($account, $jira_key); + } + break; } catch (HTTPFutureResponseStatus $ex) { phlog($ex); @@ -169,6 +170,64 @@ return $try_users; } + private static function shouldPostComment() { + return PhabricatorEnv::getEnvConfig('jira.post-comment'); + } + + private static function shouldPostLink() { + return PhabricatorEnv::getEnvConfig('jira.post-link'); + } + + private function postComment($account, $jira_key) { + $provider = $this->getProvider(); + $object = $this->getStoryObject(); + $publisher = $this->getPublisher(); + $uri = $publisher->getObjectURI($object); + + $provider->newJIRAFuture( + $account, + 'rest/api/2/issue/'.$jira_key.'/comment', + 'POST', + array( + 'body' => $this->renderStoryText(), + ))->resolveJSON(); + } + + private function postLink($account, $jira_key) { + $provider = $this->getProvider(); + $object = $this->getStoryObject(); + $publisher = $this->getPublisher(); + $uri = $publisher->getObjectURI($object); + $base_uri = PhabricatorEnv::getEnvConfig('phabricator.base-uri'); + + $provider->newJIRAFuture( + $account, + 'rest/api/2/issue/'.$jira_key.'/remotelink', + 'POST', + + // format documented at http://bit.ly/1K5T0Li + array( + 'globalId' => 'phabricatorPhid='.$object->getPHID(), + 'application' => array( + 'type' => 'org.phabricator.differential', + 'name' => 'Differential', + ), + 'relationship' => 'implemented in', + 'object' => array( + 'url' => $uri, + 'title' => $object->getMonogram(), + 'summary' => $object->getTitle(), + 'icon' => array( + 'url16x16' => $base_uri.'rsrc/favicons/favicon-16x16.png', + 'title' => 'Revision', + ), + 'status' => array( + 'resolved' => $publisher->isObjectClosed($object), + ), + ), + ))->resolveJSON(); + } + private function renderStoryText() { $object = $this->getStoryObject(); $publisher = $this->getPublisher();