最近、Railsアプリからjira-rubyというgemを使って、プロジェクト管理ツールであるJiraのREST APIでJiraに課題を追加したり更新したりできるようにしたので、その方法を書いていきます。
jira-rubyに関する日本語の記事は少ないみたいなので、誰かの手助けになれば幸いです。
今回は、前回のJiraのOAuth認証の実装ができていることを前提として、
課題の更新や追加に関して書いていきます。
バージョン
ruby 2.2.0
rails 4.2.1
Jira Software Server 7.11.2
Jiraのプロジェクトの取得方法
プロジェクトはプロジェクトIDやkeyを指定して取得できます。
# 全てのプロジェクトを取得
@client.Project.all
# プロジェクトのidを指定して取得
@client.Project.find(2)
# プロジェクトのキーを指定して取得
@client.Project.find('SAMPLEPROJECT-1')
課題の取得方法
課題もプロジェクト同様に、課題IDとkeyを指定して取得できます。
存在しない課題の場合、JIRA::HTTPErrorになります。
# 全ての課題を取得
@client.Issue.all
# 課題IDを指定して取得
@client.Issue.find(1000)
ステータスの取得方法
ステータスもよく似た方法で取得できます。
# 全てのステータスを取得
@client.Status.all
# ステータスIDを指定して取得
@client.Status.find(id)
優先度取得方法
優先度も同様です。
# 全ての優先度を取得
@client.Priority.all
# IDを指定して取得
@client.Priority.find(id)
課題タイプの取得方法
課題タイプはプロジェクトに紐づいているので、プロジェクトを特定してから取得します。
@client.Project.find(id).issuetypes
課題の更新方法
課題を更新するときは、まず更新したい課題を取得します。
issue = @client.Issue.find(id)
次に、更新したいパラメータのみfieldsをkeyとして、値に付与します。
idが必要なものはidをkeyにしましょう。
issue.save({"fields" => {
"project" => {"id" => 2},
"summary" => "hogehogesummary"],
"issuetype" => {"id" => 3}
}})
issue.fetch
課題の追加方法
課題の追加はより複雑です。
単純に課題を追加するには、以下のようにできます。
issue = client.Issue.build
labels = ['label1', 'label2']
issue.save({
"fields" => {
"summary" => "blarg from in example.rb",
"project" => {"key" => "SAMPLEPROJECT"},
"issuetype" => {"id" => "3"},
"labels" => labels,
"priority" => {"id" => "1"}
}
})
issue.fetch
ただ、Jiraでは非常に細かく設定をカスタマイズできます。
課題のフィールドの入力の許可設定ページ(/secure/admin/ViewIssueFields.jspa)では、
必須フィールド以外のフィールドを入力禁止にすることができます。
禁止されているフィールドを追加しようとするとエラーになるので、
私の場合は、以下のように、必須項目以外は一つずつ更新していきました。
issue = @client.Issue.build
# dataは送信したい詳細データ
issue = create_or_update_issue(data, issue)
# 必須フィールド入力してとりあえず課題を生成。
def create_or_update_issue(data, issue)
begin
issue.save({"fields" => {
"project" => {"id" => "#{data["projectId"]}"},
"summary" => data["summary"],
"issuetype" => {"id" => "#{data["issueTypeId"]}"}
}})
rescue JIRA::HTTPError
issue
end
issue
end
# 上手く課題を生成できれば、残りのフィールドを追加するために、その課題を更新していく。
unless issue.try(:errors) || issue.try(:errorMessages)
update_unrequire_fields(data, issue.id)
end
# 必須フィールド以外のフィールドの追加
def update_unrequire_fields(data, issue_id)
unrequire_keys = %w(description priorityId duedate)
unrequire_keys.each do |key|
begin
issue = @client.Issue.find(issue_id)
issue.save({"fields" => {new_key => (key.include?('Id') ? {"id" => "#{data[key]}"} : "#{data[key]}")}})
rescue JIRA::HTTPError
nil
end
end
end
課題のステータスの更新方法
ステータスを更新するのは一工夫必要です。
Jiraをお使いであれば、わかると思いますが、Jiraではステータスを変更するときはトランジションを指定します。
REST APIでも一緒です。
ステータスを変更するときはトランジションを指定しなければいけません。
issue = @client.Issue.find(issue_id)
# 変更したいステータスを取得
new_status_name = self.Status.find(status_id).name
# 課題に紐づいているトランジションを全て取得します。
# トランジションとステータスは1対1の関係にあり、toメソッドで変更されるステータスを取得することができます。
# トランジションで変更されるステータスと変更したいステータスを照合して、合致するものを取得します。
begin
jira_transitions_id = issue.transitions.all.find{|jt| jt.to.name == new_status_name }.id
rescue StandardError
jira_transitions_id = false
end
if jira_transitions_id
# 課題に紐づくトランジションをbuildしてからseveします。
issue_transition = issue.transitions.build
issue_transition.save!('transition' => { 'id' => jira_transitions_id})
end
エラーハンドリング
エラーとしては、APIではほぼ課題に関するものはほぼ全て、JIRA::HTTPErrorになります。
ステータスコードは大抵400です。
詳しくはこちらをご覧ください。
ただ、saveするときに失敗した場合は、issue.errorsもしくはissue.errorMessagesにエラーメッセージが入っています。
アクセストークンが有効ではない場合と認証タイプが違う場合はOAuth::Problemになります。
まとめ
私が試したJiraの課題に関するところは以上となります。
Jiraは非常にカスタマイズできる項目が多いため、中々REST APIで対応するのは難しかったです。
何かご指摘があればコメントください。