JIRA APIを使用してチケットを作成する

JIRAは便利だけど、チケット作るの面倒！
定期的に作る必要があったり、細かく起票ルールが決まっている場合は、どうにか自動化させたいですよね。

その第一歩としてまずはJIRA APIを使用してチケットを作成してみました。

## 使用するAPI
- JIRA Login API
- JIRA Create issue API

## 環境
- JIRA Software v7.3.6
- Node v9.11.1

## 全体の流れ
```js:app.js
function main () {
  const request = require('request')
  const JIRA_URI = 'https://jira.hogehoge.co.jp/'

  return loginJIRA()
    .then(function (data) {
      return createIssue(data.session.name, data.session.value)
    })
    .then(function (data) {
      console.log('create　ticket id:' + data.key)
    })
}
```
チケット作成APIを実行する上で、まずログインAPIを実行し、JIRAセッションを取得する必要があります。
JIRAセッションをcreate issueAPIに渡し、チケットを作成します。

## ログインAPI
```js:login.js
  function loginJIRA () {
    let options = {
      uri: JIRA_URI + 'rest/auth/1/session',
      headers: {
        'Content-type': 'application/json'
      },
      body: {
        username: 'username',
        password: 'hogehoge'
      },
      method: 'POST',
      json: true
    }

    return new Promise(function (resolve, reject) {
      request(options, function (error, response, data) {
        if (!error && response.statusCode === 200) {
          console.log('JIRA login success!!')
          resolve(data)
        } else {
          console.log('error: ' + response.statusCode + ': ' + data.errorMessages[0])
          reject(data.errorMessages[0])
        }
      })
    })
  }
```

```js:ログインAPIのレスポンス
{ session:
   { name: 'JSESSIONID',
     value: 'ABCDEFGHABCDEFGHABCDEFGHABCDEFGH' },
  loginInfo:
   { failedLoginCount: 30,
     loginCount: 5507,
     lastFailedLoginTime: '2018-04-11T00:45:19.514+0900',
     previousLoginTime: '2018-06-30T18:21:36.614+0900' } }
```
JIRA APIを利用するためにはsession.nameとsession.valueが必要になります。

## チケット作成API
```js:createIssue.js
  function createIssue (sessionName, sessionValue) {
    let payload = {
      fields: {
        project: {
          key: 'TEST'
        },
        summary: 'チケットタイトル',
        assignee: { // 担当者
          name: 'username'
        },
        priority: { // 優先度
          id: '3'
        },
        issuetype: { // チケットタイプ
          id: '3'
        },
        description: 'チケット説明'
      }
    }

    let options = {
      uri: JIRA_URI + '/rest/api/2/issue',
      headers: {
        'Content-type': 'application/json',
        cookie: sessionName + '=' + sessionValue
      },
      body: payload,
      method: 'POST',
      json: true
    }

    return new Promise(function (resolve, reject) {
      request(options, function (error, response, data) {
        if (!error && response.statusCode === 201) {
          console.log('JIRA ticket create success!!')
          resolve(data)
        } else {
          console.log('error: ' + response.statusCode + ': ' + data.errorMessages)
          reject(data.errorMessages)
        }
      })
    })
  }
```
```js:チケット作成APIのレスポンス
{ id: '123456',
  key: 'TEST-123',
  self: 'https://jira.hogehoge.co.jp/rest/api/2/issue/123456' }
```
チケット作成APIのヘッダーにログインAPIで取得したセッションが必要になります。

今回はプロジェクト、タイトル、担当者、優先度、チケットタイプ、説明のみ指定しています。

チケットタイプ、優先度のIDがわからない場合は下記のAPIで調べることができます。
※jira.hogehoge.co.jpは使用しているJIRAのURLに変更してください。
チケットタイプ： https://jira.hogehoge.co.jp/rest/api/2/issuetype
優先度： https://jira.hogehoge.co.jp/rest/api/2/priority


## まとめ
簡単なチケットであればこれで作成できそうです。
サブタスクや親子チケット、その他のフィールドを指定するチケットについては別途まとめようと思います。

## 参考
[JIRA Server platform REST API reference(JIRA 7.3.6)](https://docs.atlassian.com/software/jira/docs/api/REST/7.3.6/)

<details><summary>サンプルコード</summary><div>
## サンプルコード
```js:app.js
function main () {
  const request = require('request')
  const JIRA_URI = 'https://jira.hogehoge.co.jp/'

  return loginJIRA()
    .then(function (data) {
      return createIssue(data.session.name, data.session.value)
    })
    .then(function (data) {
      console.log('create　ticket id:' + data.key)
    })

  function loginJIRA () {
    let options = {
      uri: JIRA_URI + 'rest/auth/1/session',
      headers: {
        'Content-type': 'application/json'
      },
      body: {
        username: 'username',
        password: 'hogehoge'
      },
      method: 'POST',
      json: true
    }

    return new Promise(function (resolve, reject) {
      request(options, function (error, response, data) {
        if (!error && response.statusCode === 200) {
          console.log('JIRA login success!!')
          resolve(data)
        } else {
          console.log('error: ' + response.statusCode + ': ' + data.errorMessages[0])
          reject(data.errorMessages[0])
        }
      })
    })
  }

  function createIssue (sessionName, sessionValue) {
    let payload = {
      fields: {
        project: {
          key: 'TEST'
        },
        summary: 'チケットタイトル',
        assignee: { // 担当者
          name: 'username'
        },
        priority: { // 優先度
          id: '3'
        },
        issuetype: { // チケットタイプ
          id: '3'
        },
        description: 'チケット説明'
      }
    }

    let options = {
      uri: JIRA_URI + '/rest/api/2/issue',
      headers: {
        'Content-type': 'application/json',
        cookie: sessionName + '=' + sessionValue
      },
      body: payload,
      method: 'POST',
      json: true
    }

    return new Promise(function (resolve, reject) {
      request(options, function (error, response, data) {
        if (!error && response.statusCode === 201) {
          console.log('JIRA ticket create success!!')
          resolve(data)
        } else {
          console.log('error: ' + response.statusCode + ': ' + data.errorMessages)
          reject(data.errorMessages)
        }
      })
    })
  }
}

main()
```

```sh:実行結果
$ node app.js
JIRA login success!!
JIRA ticket create success!!
create:TEST-123
```
</div></details>