1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-19 03:50:54 +01:00

JIRA Integration: Link and/or Comment

Summary:
Current JIRA integration is quite noisy in terms of email, and makes users hunt and peck for the related revisions.

Teach it to create an Issue Link on the JIRA side, and allow to disable commenting.

Test Plan: comment on revision in each of the 4 settings, check JIRA end for expected result.

Reviewers: btrahan, eMxyzptlk, epriestley, #blessed_reviewers, avivey

Reviewed By: epriestley, #blessed_reviewers

Subscribers: avivey, vhbit, jra3, eMxyzptlk, frenchs, aik099, svemir, rmuslimov, cpa199, waynea, epriestley, Korvin, hach-que

Projects: #doorkeeper

Maniphest Tasks: T5422

Differential Revision: https://secure.phabricator.com/D9858
This commit is contained in:
Aviv Eyal 2015-11-12 19:30:43 +00:00 committed by turadg
parent 7e3d8082df
commit e8fdf478bb
2 changed files with 123 additions and 11 deletions

View file

@ -77,6 +77,8 @@ final class PhabricatorJIRAAuthProvider extends PhabricatorOAuth1AuthProvider {
const PROPERTY_JIRA_URI = 'oauth1:jira:uri'; const PROPERTY_JIRA_URI = 'oauth1:jira:uri';
const PROPERTY_PUBLIC_KEY = 'oauth1:jira:key:public'; const PROPERTY_PUBLIC_KEY = 'oauth1:jira:key:public';
const PROPERTY_PRIVATE_KEY = 'oauth1:jira:key:private'; const PROPERTY_PRIVATE_KEY = 'oauth1:jira:key:private';
const PROPERTY_REPORT_LINK = 'oauth1:jira:report:link';
const PROPERTY_REPORT_COMMENT = 'oauth1:jira:report:comment';
public function readFormValuesFromProvider() { public function readFormValuesFromProvider() {
@ -100,6 +102,10 @@ final class PhabricatorJIRAAuthProvider extends PhabricatorOAuth1AuthProvider {
return array( return array(
self::PROPERTY_JIRA_NAME => $name, self::PROPERTY_JIRA_NAME => $name,
self::PROPERTY_JIRA_URI => $request->getStr(self::PROPERTY_JIRA_URI), self::PROPERTY_JIRA_URI => $request->getStr(self::PROPERTY_JIRA_URI),
self::PROPERTY_REPORT_LINK =>
$request->getInt(self::PROPERTY_REPORT_LINK, 0),
self::PROPERTY_REPORT_COMMENT =>
$request->getInt(self::PROPERTY_REPORT_COMMENT, 0),
); );
} }
@ -175,6 +181,7 @@ final class PhabricatorJIRAAuthProvider extends PhabricatorOAuth1AuthProvider {
'JIRA 5 or earlier.')); 'JIRA 5 or earlier.'));
$is_setup = $this->isSetup(); $is_setup = $this->isSetup();
$viewer = $request->getViewer();
$e_required = $request->isFormPost() ? null : true; $e_required = $request->isFormPost() ? null : true;
@ -249,11 +256,40 @@ final class PhabricatorJIRAAuthProvider extends PhabricatorOAuth1AuthProvider {
id(new AphrontFormStaticControl()) id(new AphrontFormStaticControl())
->setLabel(pht('Public Key')) ->setLabel(pht('Public Key'))
->setValue($pkey)); ->setValue($pkey));
$form
->appendRemarkupInstructions(
pht(
'= Integration Options = '."\n".
'Configure how to record Revisions on JIRA tasks.'."\n\n".
'Note you\'ll have to restart the daemons for this to take '.
'effect.'))
->appendChild(
id(new AphrontFormCheckboxControl())
->addCheckbox(
self::PROPERTY_REPORT_LINK,
1,
new PHUIRemarkupView(
$viewer,
pht(
'Create **Issue Link** to the Revision, as an "implemented '.
'in" relationship.')),
$this->shouldCreateJIRALink()))
->appendChild(
id(new AphrontFormCheckboxControl())
->addCheckbox(
self::PROPERTY_REPORT_COMMENT,
1,
new PHUIRemarkupView(
$viewer,
pht(
'**Post a comment** in the JIRA task, similar to the '.
'emails Phabricator sends.')),
$this->shouldCreateJIRAComment()));
} }
} }
/** /**
* JIRA uses a setup step to generate public/private keys. * JIRA uses a setup step to generate public/private keys.
*/ */
@ -286,4 +322,14 @@ final class PhabricatorJIRAAuthProvider extends PhabricatorOAuth1AuthProvider {
return $adapter->newJIRAFuture($path, $method, $params); return $adapter->newJIRAFuture($path, $method, $params);
} }
public function shouldCreateJIRALink() {
$config = $this->getProviderConfig();
return $config->getProperty(self::PROPERTY_REPORT_LINK, true);
}
public function shouldCreateJIRAComment() {
$config = $this->getProviderConfig();
return $config->getProperty(self::PROPERTY_REPORT_COMMENT, true);
}
} }

View file

@ -40,6 +40,14 @@ final class DoorkeeperJIRAFeedWorker extends DoorkeeperFeedWorker {
return; return;
} }
$do_anything = ($this->shouldPostComment() || $this->shouldPostLink());
if (!$do_anything) {
$this->log(
"%s\n",
pht('JIRA integration is configured not to post anything.'));
return;
}
$xobjs = id(new DoorkeeperExternalObjectQuery()) $xobjs = id(new DoorkeeperExternalObjectQuery())
->setViewer($viewer) ->setViewer($viewer)
->withPHIDs($jira_issue_phids) ->withPHIDs($jira_issue_phids)
@ -60,7 +68,6 @@ final class DoorkeeperJIRAFeedWorker extends DoorkeeperFeedWorker {
return; return;
} }
$story_text = $this->renderStoryText();
$xobjs = mgroup($xobjs, 'getApplicationDomain'); $xobjs = mgroup($xobjs, 'getApplicationDomain');
foreach ($xobjs as $domain => $xobj_list) { foreach ($xobjs as $domain => $xobj_list) {
@ -84,13 +91,16 @@ final class DoorkeeperJIRAFeedWorker extends DoorkeeperFeedWorker {
foreach ($xobj_list as $xobj) { foreach ($xobj_list as $xobj) {
foreach ($accounts as $account) { foreach ($accounts as $account) {
try { try {
$provider->newJIRAFuture( $jira_key = $xobj->getObjectID();
$account,
'rest/api/2/issue/'.$xobj->getObjectID().'/comment', if ($this->shouldPostComment()) {
'POST', $this->postComment($account, $jira_key);
array( }
'body' => $story_text,
))->resolveJSON(); if ($this->shouldPostLink()) {
$this->postLink($account, $jira_key);
}
break; break;
} catch (HTTPFutureResponseStatus $ex) { } catch (HTTPFutureResponseStatus $ex) {
phlog($ex); phlog($ex);
@ -169,14 +179,70 @@ final class DoorkeeperJIRAFeedWorker extends DoorkeeperFeedWorker {
return $try_users; return $try_users;
} }
private function shouldPostComment() {
return $this->getProvider()->shouldCreateJIRAComment();
}
private function shouldPostLink() {
return $this->getProvider()->shouldCreateJIRALink();
}
private function postComment($account, $jira_key) {
$provider = $this->getProvider();
$provider->newJIRAFuture(
$account,
'rest/api/2/issue/'.$jira_key.'/comment',
'POST',
array(
'body' => $this->renderStoryText(),
))->resolveJSON();
}
private function renderStoryText() { private function renderStoryText() {
$object = $this->getStoryObject(); $object = $this->getStoryObject();
$publisher = $this->getPublisher(); $publisher = $this->getPublisher();
$text = $publisher->getStoryText($object); $text = $publisher->getStoryText($object);
$uri = $publisher->getObjectURI($object);
return $text."\n\n".$uri; if ($this->shouldPostLink()) {
return $text;
} else {
// include the link in the comment
return $text."\n\n".$publisher->getObjectURI($object);
}
} }
private function postLink($account, $jira_key) {
$provider = $this->getProvider();
$object = $this->getStoryObject();
$publisher = $this->getPublisher();
$icon_uri = celerity_get_resource_uri('rsrc/favicons/favicon-16x16.png');
$provider->newJIRAFuture(
$account,
'rest/api/2/issue/'.$jira_key.'/remotelink',
'POST',
// format documented at http://bit.ly/1K5T0Li
array(
'globalId' => $object->getPHID(),
'application' => array(
'type' => 'com.phacility.phabricator',
'name' => 'Phabricator',
),
'relationship' => 'implemented in',
'object' => array(
'url' => $publisher->getObjectURI($object),
'title' => $publisher->getObjectTitle($object),
'icon' => array(
'url16x16' => $icon_uri,
'title' => 'Phabricator',
),
'status' => array(
'resolved' => $publisher->isObjectClosed($object),
),
),
))->resolveJSON();
}
} }