mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 08:52:39 +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:
parent
7e3d8082df
commit
e8fdf478bb
2 changed files with 123 additions and 11 deletions
|
@ -77,6 +77,8 @@ final class PhabricatorJIRAAuthProvider extends PhabricatorOAuth1AuthProvider {
|
|||
const PROPERTY_JIRA_URI = 'oauth1:jira:uri';
|
||||
const PROPERTY_PUBLIC_KEY = 'oauth1:jira:key:public';
|
||||
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() {
|
||||
|
@ -100,6 +102,10 @@ final class PhabricatorJIRAAuthProvider extends PhabricatorOAuth1AuthProvider {
|
|||
return array(
|
||||
self::PROPERTY_JIRA_NAME => $name,
|
||||
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.'));
|
||||
|
||||
$is_setup = $this->isSetup();
|
||||
$viewer = $request->getViewer();
|
||||
|
||||
$e_required = $request->isFormPost() ? null : true;
|
||||
|
||||
|
@ -249,11 +256,40 @@ final class PhabricatorJIRAAuthProvider extends PhabricatorOAuth1AuthProvider {
|
|||
id(new AphrontFormStaticControl())
|
||||
->setLabel(pht('Public Key'))
|
||||
->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.
|
||||
*/
|
||||
|
@ -286,4 +322,14 @@ final class PhabricatorJIRAAuthProvider extends PhabricatorOAuth1AuthProvider {
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,6 +40,14 @@ final class DoorkeeperJIRAFeedWorker extends DoorkeeperFeedWorker {
|
|||
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())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs($jira_issue_phids)
|
||||
|
@ -60,7 +68,6 @@ final class DoorkeeperJIRAFeedWorker extends DoorkeeperFeedWorker {
|
|||
return;
|
||||
}
|
||||
|
||||
$story_text = $this->renderStoryText();
|
||||
|
||||
$xobjs = mgroup($xobjs, 'getApplicationDomain');
|
||||
foreach ($xobjs as $domain => $xobj_list) {
|
||||
|
@ -84,13 +91,16 @@ final class DoorkeeperJIRAFeedWorker extends DoorkeeperFeedWorker {
|
|||
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 ($this->shouldPostComment()) {
|
||||
$this->postComment($account, $jira_key);
|
||||
}
|
||||
|
||||
if ($this->shouldPostLink()) {
|
||||
$this->postLink($account, $jira_key);
|
||||
}
|
||||
|
||||
break;
|
||||
} catch (HTTPFutureResponseStatus $ex) {
|
||||
phlog($ex);
|
||||
|
@ -169,14 +179,70 @@ final class DoorkeeperJIRAFeedWorker extends DoorkeeperFeedWorker {
|
|||
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() {
|
||||
$object = $this->getStoryObject();
|
||||
$publisher = $this->getPublisher();
|
||||
|
||||
$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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue