この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、リサリサです。
Backlog に大量の課題を一括登録したので記事にしてみます。
やりたいこと
Backlog に大量の課題を一括追加したい。100個くらい……
issue.csv に追加したい内容の一覧を作れば、それを一括で課題登録できるようにしてみました。
Backlog は登録の際、選択肢の項目を全て ID で登録しないといけません。優先度なら、高でななく2など。それを考えながら一覧を作成すると面倒なので、高から2への変換をした上で、一括登録できるようにしました。issue.csv には、高と記載して大丈夫です。(そのために事前に get_id_list.py で id_list.json を作成しています。こちらは初回と、カテゴリ追加などあった際に実行して頂ければ OK です。)
やってみた
実行環境
Python 3.8.0
準備① APIキーの発行
Backlogの認証は、APIキーを利用する場合とOAuthを利用する場合の2通りがあります。今回はAPIキーを用いてAPIの操作を行います。
APIキーは、[個人設定]->[API]から、「登録」ボタンを押すことで発行できます。発行後は、下の画面にAPIキーが表示されるので、これを用いてAPIの操作を行います。
準備② スペースキー、プロジェクトIDを取得
スペースキー
バックログのサブドメインに使われているものです。
xxx.backlog.jp
プロジェクトID
プロジェクトキーかと思いきや、ちょっと違って自動採番の数字になります。
「プロジェクト設定」のURLを見ると記載があります。
https://xxx.backlog.jp/EditProject.action?project.id=1234567890
準備③ IDリストを取得
Backlog API から課題を登録する場合、画面から登録できる「優先度」、「カテゴリー」、「担当者」など、全て ID で登録する必要があります。
それぞれ頑張ると「プロジェクト設定」などからも取得できるのですが、なかなか大変だったので、API でまとめて取得してみました。以下のpythonを実行すると、同ディレクトリに id_list.jsonが作成され、そこに各ID情報が出力されます。
APIキー、スペースキー、プロジェクトIDには、準備①②で取得したキーを記載してください。
get_id_list.py
import requests
import csv
import json
API_KEY = 'APIキー'
SPACE_KEY = 'スペースキー'
PROJECT_ID = 'プロジェクトID'
BASE_URL = f"https://{SPACE_KEY}.backlog.jp/api/v2"
def get_id(url):
params = {
'apiKey': API_KEY,
}
r = requests.get(url, params=params)
r.raise_for_status()
return json.loads(r.text)
# csvのタイトル
output = {}
print('・issueTypeId(課題の種別のID)用')
# 種別一覧の取得
# https://developer.nulab.com/ja/docs/backlog/api/2/get-issue-type-list/#
# /api/v2/projects/:projectIdOrKey/issueTypes
datas = get_id(f"{BASE_URL}/projects/{PROJECT_ID}/issueTypes")
output['issueTypeId'] = {}
for data in datas:
output['issueTypeId'][data['name']] = data['id']
print(f"{data['id']}:{data['name']}")
print('・assigneeId(課題の担当者のID)用')
# プロジェクトユーザー一覧の取得
# https://developer.nulab.com/ja/docs/backlog/api/2/get-project-user-list/#
# /api/v2/projects/:projectIdOrKey/users
datas = get_id(f"{BASE_URL}/projects/{PROJECT_ID}/users")
output['assigneeId'] = {}
for data in datas:
output['assigneeId'][data['name']] = data['id']
print(f"{data['id']}:{data['name']}")
print('・categoryId(課題のカテゴリーのID)用')
# カテゴリー一覧の取得
# https://developer.nulab.com/ja/docs/backlog/api/2/get-category-list/#
# /api/v2/projects/:projectIdOrKey/categories
datas = get_id(f"{BASE_URL}/projects/{PROJECT_ID}/categories")
output['categoryId[]'] = {}
for data in datas:
output['categoryId[]'][data['name']] = data['id']
print(f"{data['id']}:{data['name']}")
print('・versionId(課題の発生バージョンのID)、milestoneId(課題のマイルストーンのID)用')
# バージョン(マイルストーン)一覧の取得
# https://developer.nulab.com/ja/docs/backlog/api/2/get-version-milestone-list/#
# /api/v2/projects/:projectIdOrKey/versions
datas = get_id(f"{BASE_URL}/projects/{PROJECT_ID}/versions")
output['versionId'] = {}
output['milestoneId'] = {}
for data in datas:
output['versionId'][data['name']] = data['id']
output['milestoneId'][data['name']] = data['id']
print(f"{data['id']}:{data['name']}")
print('・priorityId(課題の優先度のID)用')
# 優先度一覧の取得
# https://developer.nulab.com/ja/docs/backlog/api/2/get-priority-list/#
# /api/v2/priorities
datas = get_id(f"{BASE_URL}/priorities")
output['priorityId'] = {}
for data in datas:
output['priorityId'][data['name']] = data['id']
print(f"{data['id']}:{data['name']}")
# customField_{id}(カスタム属性の値)用
# カスタム属性一覧の取得
# https://developer.nulab.com/ja/docs/backlog/api/2/get-custom-field-list/#
# /api/v2/projects/:projectIdOrKey/customFields
datas = get_id(f"{BASE_URL}/projects/{PROJECT_ID}/customFields")
for data in datas:
print(f"・customField_{data['id']}({data['name']})用")
output[f"customField_{data['id']}"] = {}
for item in data['items']:
output[f"customField_{data['id']}"][item['name']] = item['id']
print(f"{item['id']}:{item['name']}")
with open('id_list.json', 'w') as f:
f.write(json.dumps(output, indent=4, ensure_ascii=False))
id_list.json は以下のようになっています。
id_list.json
{
"issueTypeId": {
"Parent Issue": 1074831859,
"event": 1074838719,
"Task": 1074821804,
"Bug": 1074821803,
"Request": 1074821805,
"Other": 1074821806
},
"assigneeId": {
"田中": 1074281901,
"木村": 1074201141,
"佐藤": 1074121619
},
"categoryId[]": {
"外部設計": 1074361053,
"内部設計": 1074365061,
"プロジェクト管理": 1074371210
},
"versionId": {
"第1フェーズ": 1074285907,
"第2フェーズ": 1074285906
},
"milestoneId": {
"第1フェーズ": 1074285907,
"第2フェーズ": 1074285906
},
"priorityId": {
"高": 2,
"中": 3,
"低": 4
},
"customField_1073851824": {
"xxxxx": 1,
"yyyyy": 1
}
}
追加したい課題一覧を作成
Excelやスプレッドシートで一覧を作り、csvに変換します。
項目は以下のパラメーターから必要なものを使ってください。issueTypeId(課題種別),priorityId(優先度),summary(件名)以外の項目であれば、空欄があっても大丈夫ですし、列自体なくても大丈夫です。日付は「yyyy-mm-dd」で記載ください。※複数指定は対応してません。
項目名も選択肢(特に担当者名など)も、機械的にIDに変換して、APIを叩いているだけですので、一言一句間違わずに入力してください…
スプレッドシートの場合は、ファイル⇒ダウンロード⇒csvからcsvに変換できます。
issue.csv
issueTypeId,parentIssueId,priorityId,summary,description,assigneeId,startDate,dueDate,categoryId[],customField_1073853234
Parent Issue,PROJECT-1,中,xxxxの設計,xxxxの設計についての詳細,田中,2022-03-29,2022-04-09,内部設計,xxxxxx
Parent Issue,PROJECT-1,中,yyyyの設計,yyyyの設計についての詳細,佐藤,,,内部設計,xxxxxx
id_list.json と同じディレクトリに issue.csv という名前で保存してください。
登録する
id_list.json 、issue.csv と同じディレクトリで実行すると、Backlog に課題登録できます。※バリデーションチェック等していないので、項目名に間違いがあったりするとエラーで落ちます。
APIキー、スペースキー、プロジェクトIDには、準備①②で取得したキーを記載してください。
create_issue.py
import requests
import csv
import json
API_KEY = 'APIキー'
SPACE_KEY = 'スペースキー'
PROJECT_ID = 'プロジェクトID'
BASE_URL = f"https://{SPACE_KEY}.backlog.jp/api/v2"
def add_issue(payload):
url = f"{BASE_URL}/issues"
payload['projectId'] = PROJECT_ID
params = {
'apiKey': API_KEY,
}
r = requests.post(url, params=params, data=payload)
r.raise_for_status()
return r
def get_issue_id(issue_key):
url = f"{BASE_URL}/issues/{issue_key}"
params = {
'apiKey': API_KEY,
}
r = requests.get(url, params=params, data=payload)
r.raise_for_status()
print('get_issue')
return json.loads(r.text)["id"]
# idリストを取得
with open('id_list.json') as f:
id_list = json.load(f)
# 親課題登録用のidリスト
issue_id_list = {}
with open('issue.csv') as f:
reader = csv.DictReader(f)
for r in reader:
payload = {}
print(r)
# 選択肢⇒idへ変換
for k, v in r.items():
# 親課題だけidを取得するためにget issueが必要
if k == 'parentIssueId':
if not v in issue_id_list:
issue_id_list[v] = get_issue_id(v)
payload[k] = issue_id_list[v]
else:
if v:
if k in id_list:
payload[k] = id_list[k][v]
else:
payload[k] = v
print(payload)
# 課題登録
add_issue(payload)
画面から追加したのと同じように、課題の追加ができました。
最後に
大量の課題追加が必要な誰かのお役に立てれば幸いです。