%META:TOPICINFO{author="TWikiContributor" date="1442437186" format="1.1" version="$Rev$"}%
---+ JIRA REST Plugin
<!--
   Contributions to this plugin are appreciated. Please update the plugin page at
   http://twiki.org/cgi-bin/view/Plugins/JiraRestPlugin or provide feedback at
   http://twiki.org/cgi-bin/view/Plugins/JiraRestPluginDev.
   If you are a TWiki contributor please update the plugin in the SVN repository.
-->
<sticky>
<div style="float:right; background-color:#EBEEF0; margin:0 0 20px 20px; padding: 0 10px 0 10px;">
%TOC{title="Page contents"}%
</div>
</sticky>
%SHORTDESCRIPTION%

---++ Introduction

[[Wikipedia:JIRA][JIRA]] is a popular issue and project tracker by Atlassian. Organizations using TWiki and JIRA can use this plugin to reference and update JIRA content from within TWiki topics.

%T%: __Tip:__ This plugin is generic enough, it can used to establish REST connections to data sources other than JIRA.

Alternatives to this plugin:

   * Create your own issue and project tracker in TWiki using %SYSTEMWEB%.TWikiForms and %SYSTEMWEB%.FormattedSearch.
   * %IF{ "istopic '%SYSTEMWEB%.JiraPluginx'" then="%SYSTEMWEB%.JiraPlugin" else="TWiki:Plugins.JiraPlugin (not installed)" }% - display JIRA issues using JQL search.

---++ Description

This plugin handles a =%<nop>JIRAREST{}%= variable. Use it to get, create and update content in JIRA. The JIRAREST variables makes a REST ([[Wikipedia:Representational_state_transfer][Representational state transfer]]) API call to a JIRA server. Data sent to JIRA and received from JIRA is in [[Wikipedia:JSON][JSON]] format.

<img src="%PUBURLPATH%/%WEB%/%TOPIC%/diagram.png" alt="diagram.png" width="497" height="138" />

---+++ User authentication

The user is identified on the JIRA sever with user name and password using [[Wikipedia:Basic_access_authentication][basic authentication]], specified either in the configuration (default user), or as JIRAREST parameters.

%X% __NOTE:__ Basic authentication transmit user and password unencrypted. Because of this we recommend to run the TWiki server and the REST connection between the TWiki server and the JIRA server under TLS ([[Wikipedia:Transport_Layer_Security][Transport Layer Security]], "https:" protocol) only.

---+++ Interactive JIRA REST API Query

<sticky>
<div style="float:right; width: 427px; background-color:#EBEEF0; margin:0 0 20px 20px; padding: 10px 10px;">
[[JiraRestQuery][<img src="%PUBURLPATH%/%WEB%/%TOPIC%/jira-rest-query.png" alt="jira-rest-query.png" width="427" height="229" />]]
</div>
</sticky>
Use the *[[JiraRestQuery][JIRA REST API query form]]* to interactively send REST requests to the JIRA server. The query form asks for the action (REST method), command (REST API call), data (for PUT and POST methods), user and password. Omit the user and password if you want to use the default user and password specified in configure. Specifying the password is safe as long as the TWiki server enforces TLS.

To learn the JIRA REST API commands read the [[https://docs.atlassian.com/jira/REST/latest/][JIRA REST API documentation]].

---++ Syntax Rules

%INCLUDE{"VarJIRAREST"}%

---+++ JSON Response

The =%<nop>JIRAREST{}%= variable returns a [[Wikipedia:JSON][JSON]] object with the following format:

<pre>
{ "code": <i>CODE</i>, "content": <i>CONTENT</i>, "error": <i>ERROR</i>, "header": <i>HEADER</i> }
</pre>

   * =<i>CODE</i>= - response code; example: =201=
   * =<i>CONTENT</i>= - response data, in JSON format; example: ={ "id": "59935", "key": "TEST-6952", "self": "http://jira.example.com/jira/rest/api/2/issue/59935" }=
   * =<i>ERROR</i>= - error message; empty string =""= if no error; example: ="POST '/api/2/issue/' returns code 400"=
   * =<i>HEADER</i>= - response header, only shown if ={Plugins}{JiraRestPlugin}{Debug}= is set to 2; example: ={ "Cache-Control": "no-cache, no-store, no-transform", "Connection": "close", ... }=

%T% __Tip:__ Use the SetGetPlugin to traverse and extract content from the JSON response. See interactive [[JiraRestQuery][JIRA REST API query form]].

It is possible to issue multiple REST API calls in one session using =action="..." command="..." data="..." action2="..." command2="..." data2="..."= etc. Example JSON response with three actions:

<verbatim>
{ "code": 200, "content": {...}, "error": "",
  "code2": 200, "content2": {...}, "error2": "",
  "code3": 200, "content3": {...}, "error3": "" }
</verbatim>

---+++ JSON back reference

It is possible to use returned content as input for subsequent =command&lt;N&gt;="..."= and =data&lt;N&gt;="..."=. For example, in the first =command="..."= you create an issue of type Epic, and in =command2="..."= you want to create a Story issue, using the key returned by the first command as the "Epic Link" in the Story.

The syntax of a JSON back reference to the content of the first command is =$(content.&lt;name&gt;)=, such as =$(content.key)=. For example, the back reference to object "ID" in the content of the second command is =$(content2.ID)=

See example to [[#CreateNewEpic][create an Epic and a Story]], using a JSON back reference to set the Epic Link in the Story.

__Notes:__
   * If the value of a back reference is a string, the enclosing quotes are stripped.
   * At this time only top level objects can be referenced, e.g. arrays and nested objects are not supported at this time.

#JiraRestExamples
---++ JIRA REST Examples

   * You can use the [[JiraRestQuery][JIRA REST API query form]] to try these examples.
   * See [[https://developer.atlassian.com/jiradev/api-reference/jira-rest-apis/jira-rest-api-tutorials][JIRA REST API Tutorials]] to get started.
   * See [[https://docs.atlassian.com/jira/REST/latest/][JIRA REST API documentation]] for details.

---+++ Get session info of currently authenticated user

<pre>
%<nop>JIRAREST{
  action="get"
  command="/rest/auth/1/session"
  data=""
  user="admin"
  password="*****"
}%
</pre>

__JSON Response:__

={ "code": 200, "content": { "self": "http://jira.example.com/jira/rest/api/latest/user?username=admin", "name": "admin", "loginInfo": { "failedLoginCount": 59, "loginCount": 88, "lastFailedLoginTime": "2015-06-01T19:01:20.393-0700", "previousLoginTime": "2015-06-08T15:36:36.839-0700" } }, "error": "" }=

---+++ Create new issue in TEST project

<pre>
%<nop>JIRAREST{
  action="post"
  command="/rest/api/2/issue/"
  data="%RED%DATA%ENDCOLOR%"
  user="admin"
  password="*****"
}%
</pre>

__With %RED%DATA%ENDCOLOR% set to:__
<pre>
{
  "fields": {
    "project":
    {
      "key": "TEST"
    },
    "summary": "REST ye merry gentlemen.",
    "description": "Creating an issue using project key and issue type name via the REST API",
    "versions": [ { "name": "1.2" } ],
    "components": [ { "name": "ESC" } ],
    "issuetype": {
      "name": "Task"
    }
  }
}
</pre>

__Note:__ Quotes in DATA need to be escaped, such as =\"fields\"=. No escaping is needed when the [[JiraRestQuery][JIRA REST API query form]] is used.

__JSON Response:__

={ "code": 201, "content": { "id": "59937", "key": "TEST-6953", "self": "http://jira.example.com/jira/rest/api/2/issue/59937" }, "error": "" }=

---+++ Post a comment to an issue in TEST project

<pre>
%<nop>JIRAREST{
  action="post"
  command="/rest/api/2/issue/TEST-6953/comment?expand"
  data="{ \"body\": \"This is a comment submitted via JIRA REST API.\" }"
  user="admin"
  password="*****"
}%
</pre>

__Note:__ Quotes in the data parameter are escaped. No escaping is needed when the [[JiraRestQuery][JIRA REST API query form]] is used: ={ "body": "This is a comment submitted via JIRA REST API." }=

__JSON Response:__

={ "code": 201, "content": { "self": "http://jira.example.com/jira/rest/api/2/issue/59937/comment/161767", "id": "161767", "author": { "self": "http://jira.example.com/jira/rest/api/2/user?username=admin", "name": "admin", __...__ }, "error": "" }=

---+++ Get an issue in TEST project

<pre>
%<nop>JIRAREST{
  action="get"
  command="/rest/api/2/issue/TEST-6953"
  data=""
  user="admin"
  password="*****"
}%
</pre>

__JSON Response:__

={ "code": 200, "content": { "expand": "renderedFields,names,schema,transitions,operations,editmeta,changelog", "id": "59937", "self": "http://jira.example.com/jira/rest/api/2/issue/59937", "key": "TEST-6953", "fields": { "progress": { "progress": 0, "total": 0 }, "summary": "REST ye merry gentlemen.", ... }, "error": "" }=

#CreateNewEpic
---+++ Create new Epic and Story in JIRA Agile's TP project

This is a more complex example issuing two commands in one session. The first command creates an Epic, the second command creates a Story linked to the newly created Epic.

<pre>
%<nop>JIRAREST{
  action="post"
  command="/rest/api/2/issue/"
  data="%RED%DATA%ENDCOLOR%"
  action2="post"
  command2="/rest/api/2/issue/"
  data2="%RED%DATA2%ENDCOLOR%"
  user="admin"
  password="*****"
}%
</pre>

__With %RED%DATA%ENDCOLOR% set to:__
<pre>
{
  "fields": {
    "project":
    {
      "key": "TP"
    },
    "customfield_10704": "New Epic (via REST)",
    "summary": "Epic summary via REST API",
    "description": "Creating an Epic using project key and issue type name via the REST API",
    "issuetype": {
      "name": "Epic"
    }
  }
}
</pre>

__With %RED%DATA2%ENDCOLOR% set to:__
<pre>
{
  "fields": {
    "project":
    {
      "key": "TP"
    },
    "customfield_10701": "$(content.key)",
    "summary": "Story #1 under Epic $(content.key) via REST API",
    "description": "Creating a Story using project key and issue type name via the REST API",
    "issuetype": {
      "name": "Story"
    }
  }
}
</pre>

The =$(content.key)= is a JSON back reference to the key of the Epic created by the first command.

__Note:__ Quotes in DATA need to be escaped, such as =\"fields\"=. No escaping is needed when the [[JiraRestQuery][JIRA REST API query form]] is used.

__JSON Response:__

<pre>
{
 "error": "",
 "content": {
   "self": "http://jira.example.com/jira/rest/api/2/issue/60015",
   "id": "60015",
   "key": "TP-8"
 },
 "code": 201,
 "error2": "",
 "content2": {
   "self": "http://jira.example.com/jira/rest/api/2/issue/60016",
   "id": "60016",
   "key": "TP-9"
 },
 "code2": 201
}
</pre>

---++ Plugin Installation Instructions

You do not need to install anything on the browser to use this plugin. These instructions are for the administrator who installs the plugin on the TWiki server.

%TWISTY{
 mode="div"
 showlink="Show details %ICONURL{toggleopen}% "
 hidelink="Hide details %ICONURL{toggleclose}% "
}%

   * For an __automated installation__, run the [[%SCRIPTURL{configure}%][configure]] script and follow "Find More Extensions" in the in the __Extensions__ section.

   * Or, follow these __manual installation__ steps:
      * Download the ZIP file from the Plugins home (see below).
      * Unzip ==%TOPIC%.zip== in your twiki installation directory. Content:
        | *File:* | *Description:* |
        | ==data/TWiki/%TOPIC%.txt== | Plugin documentation |
        | ==data/TWiki/JiraRestQuery.txt== | REST API query |
        | ==data/TWiki/VarJIRAREST.txt== | JIRAREST documentation |
        | ==lib/TWiki/Plugins/%TOPIC%.pm== | Plugin Perl module |
        | ==lib/TWiki/Plugins/%TOPIC%/Core.pm== | Core Perl module |
        | ==lib/TWiki/Plugins/%TOPIC%/Config.spec== | Configuration file |
        | ==pub/TWiki/%TOPIC%/diagram.txt== | Diagram image |
      * Set the ownership of the extracted directories and files to the webserver user.

   * Install dependencies:
      * Install the REST:Client module and its dependencies

   * Plugin __configuration and testing__:
      * Run the [[%SCRIPTURL{configure}%][configure]] script and enable the plugin in the __Plugins__ section.
      * Set the following settings in the __Extensions__ section:
        %BR% ={Plugins}{JiraRestPlugin}{RestDomain}= - JIRA domain name
        %BR% ={Plugins}{JiraRestPlugin}{RestBase}= - REST base URL path
        %BR% ={Plugins}{JiraRestPlugin}{User}= - JIRA user login name
        %BR% ={Plugins}{JiraRestPlugin}{Password}= - JIRA user password
      * __Note:__ If the REST domain uses TLS (https protocol) and does not have a valid certificate, you can disable checking the validity by adding this to =twiki/lib/LocalSite.cfg=: %BR%
        =$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;=
      * Test if the installation was successful:
         * Run a query in JiraRestQuery, such as: ="get" command="/auth/1/session"=

%ENDTWISTY%

---++ Plugin Info

   * One line description, is shown in the %SYSTEMWEB%.TextFormattingRules topic:
      * Set SHORTDESCRIPTION = JIRA issue tracker interface using REST API

%TABLE{ tablewidth="100%" columnwidths="170," }%
|  Plugin Author: | TWiki:Main.PeterThoeny |
|  Copyright: | &copy; 2015 Wave Systems Corp. %BR% &copy; 2015 TWiki:Main.PeterThoeny <br /> &copy; 2015 TWiki:TWiki.TWikiContributor |
|  License: | GPL ([[http://www.gnu.org/copyleft/gpl.html][GNU General Public License]]) |
|  Sponsor: | [[http://www.wave.com/][Wave Systems Corp.]] |
|  Plugin Version: | 2015-09-16 |
%TWISTY{
 mode="div"
 showlink="Show Change History %ICONURL{toggleopen}%"
 hidelink="Hide Change History %ICONURL{toggleclose}% "
}%
%TABLE{ tablewidth="100%" columnwidths="170," }%
|  2015-09-16: | TWikibug:Item7663: Doc fix in JiraRestQuery, document use of =$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}= |
|  2015-07-24: | TWikibug:Item7663: Add support for JSON back reference to returned content, such as =$(content.key)= |
|  2015-07-06: | TWikibug:Item7663: Add example to create an Epic in JIRA Agile |
|  2015-06-15: | TWikibug:Item7663: Doc improvements |
|  2015-06-12: | TWikibug:Item7663: Ability to do multiple REST API calls in one session using =action=, =action2=, =action3=, etc. |
|  2015-06-10: | TWikibug:Item7663: Add JSON filter to interactive REST API query form; improved images |
|  2015-06-08: | TWikibug:Item7663: Return consistent JSON output; better error handling; add JIRA REST examples |
|  2015-06-05: | TWikibug:Item7663: Initial version |
%ENDTWISTY%
%TABLE{ tablewidth="100%" columnwidths="170," }%
|  TWiki Dependency: | $TWiki::Plugins::VERSION 1.1 |
|  CPAN Dependencies: |  CPAN:JSON (required for JiraRestQuery form) |
|  Other Dependencies: | SetGetPlugin version 2015-03-27 or later (required for JiraRestQuery form) |
|  Perl Version: | 5.005 |
|  [[TWiki:Plugins/Benchmark][Benchmarks]]: | %SYSTEMWEB%.GoodStyle 100%, %SYSTEMWEB%.FormattedSearch 99%, %TOPIC% 99% |
|  Plugin Home: | http://TWiki.org/cgi-bin/view/Plugins/JiraRestPlugin |
|  Feedback: | http://TWiki.org/cgi-bin/view/Plugins/JiraRestPluginDev |
|  Appraisal: | http://TWiki.org/cgi-bin/view/Plugins/JiraRestPluginAppraisal |

__Related:__ JiraRestQuery, VarJIRAREST, %SYSTEMWEB%.TWikiPlugins, %SYSTEMWEB%.DeveloperDocumentationCategory, %SYSTEMWEB%.AdminDocumentationCategory

%META:FILEATTACHMENT{name="jira-rest-query.png" attachment="jira-rest-query.png" attr="h" comment="" date="1433976844" path="jira-rest-query.png" size="31085" user="TWikiContributor" version=""}%
%META:FILEATTACHMENT{name="diagram.png" attachment="diagram.png" attr="h" comment="" date="1433976844" path="diagram.png" size="42047" user="TWikiContributor" version="1"}%
