☁️くもをもくもくまなぶ

クラウドコンピューティングサービスの学んだことを中心につらつらと書いています

Backlog APIを使ってプロジェクト管理者を抽出しよう

ヌーラボブログリレー2024 for Tech Advent Calendar 2024 7日目です。

自己紹介

2024年2月からヌーラボにジョインしています、Shibaoです。

普段は佐賀市内で生活しているのでリモートワークしています。(佐賀在住1年と少し)

Backlogのテクニカルサポートというロールで動いています。

他にはコミュニティ活動も行っていて、よかったらこちらで紹介されているのでご覧なってください。

AWS Community Builders でもあるのですが、アウトプットが少ないので、

2025年はアウトプットがんばっていきます。

佐賀市の魅力を発信する公認アンバサダーであるアンバサガーでもあります。

Backlog API

ブラウザ上のBacklogでできる操作の大部分をAPIから行うことができます。

事前準備

今回は、APIキーを使います。

APIキーの払い出し方はこちらのヘルプページに記載があります。

example.backlog.com はご自身が利用されているBacklogのURLを指定してください。

dummy123456789apikey にAPIの設定ページで払い出した値を指定してください。

$ curl "https://example.backlog.com/api/v2/users/myself?apiKey=dummy123456789apikey"
{"id":123456,"userId":"dummyUser","name":"山田太郎","roleType":1,"lang":"ja","mailAddress":"yamada.taro@example.com","nulabAccount":{"nulabId":"dummyNulabId123","name":"山田太郎","uniqueId":"t_yamada","iconUrl":"https://apps.nulab.com/account/dummyAccountId/photo/large?t=1234567890"},"keyword":"山田太郎 YAMADA TARO","lastLoginTime":"2024-03-15T10:00:00Z"}%   

上記の形で応答が返ってくれば問題ありません。

追加準備

Backlog APIの応答は、前述の通りJSON(JavaScript Object Notation)という形式で返ってくるので、必要に応じて加工できるようにするためにjqを使います。

ご自身の合うOSにダウンロード、利用できる設定をしてください。

試しに先程のAPIの実行の後ろに | jq. をつけてみます。

そうすると次のような形で応答が加工されます。

$ curl "https://example.backlog.com/api/v2/users/myself?apiKey=dummy123456789apikey" | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   420  100   420    0     0   1800      0 --:--:-- --:--:-- --:--:--  1800
{
  "id": 123456,
  "userId": "dummyUser",
  "name": "山田太郎",
  "roleType": 1,
  "lang": "ja",
  "mailAddress": "yamada.taro@example.com",
  "nulabAccount": {
    "nulabId": "dummyNulabId123",
    "name": "山田太郎",
    "uniqueId": "t_yamada",
    "iconUrl": "https://apps.nulab.com/account/dummyAccountId/photo/large?t=1234567890"
  },
  "keyword": "山田太郎 YAMADA TARO",
  "lastLoginTime": "2024-03-15T10:00:00Z"
}

jqは必要な項目のみを絞り込むことが可能です。

抽出項目の項目名を付与することも可能です。

例えば、nulabId: .nulabAccount.nulabId はAPIで返ってくる .nulabAccount.nulabId という項目の項目名をnulabId として表示するという書き方です。

$ curl "https://example.backlog.com/api/v2/users/myself?apiKey=dummy123456789apikey" | jq '{id: .id, nulabId: .nulabAccount.nulabId}'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   516  100   516    0     0   1670      0 --:--:-- --:--:-- --:--:--  1675
{
  "id": 123456,
  "nulabId": "dummyNulabId123"
}

結果が1つのデータセット(固まり)が1行で表現ができる場合は、CSV加工も可能です。

$ curl "https://example.backlog.com/api/v2/users/myself?apiKey=dummy123456789apikey" | jq -r '[.id, .nulabAccount.nulabId] | @csv'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   516  100   516    0     0   2680      0 --:--:-- --:--:-- --:--:--  2673
123456,"dummyNulabId123"

他にも記法はこちらの外部サイトで紹介されているのでご覧になってください。

目的

私はプライベートでも運営しているJAWS-UG佐賀や、コミュニティイベントでBacklogを使っています。

その中で、管理は私自身ではあるのですが、メンバの追加は他にも任せたいと思っているので、

「プロジェクト管理者」のロールをそれぞれ付与しています。

Backlogにはユーザの権限には、「管理者」「一般」「ゲスト」という大きな括りの中で、

一般ユーザには、プロジェクト管理者という権限を追加できます。

やってみる

なお実行結果の項目については2024年12月1日現在のものです。

おことわり

実行しているコマンドはmacOS、curlで行っています。

Windows 10 1803以降にもcurlが搭載されている記事は見つけましたが、

ご自身の環境でコマンドが実行できるかどうかをご確認の上実施してください。

単一のプロジェクトに対して実行する

プロジェクト管理者を取得するAPIはこちらです。
/api/v2/projects/:projectIdOrKey/administrators

  • projectIdOrKey は、 プロジェクトのID または プロジェクトキー

形式は次の通りになります。

example.backlog.com はご自身が利用されているBacklogのURLを指定してください。

EXAMPLE_PROJ はプロジェクト管理者を確認したいプロジェクトキーを指定してください。

dummy123456789apikey にAPIの設定ページで払い出した値を指定してください。

実行すると以下の形で取得できます。jq は項目の絞り込みを行っていません。

$ curl "https://example.backlog.com/api/v2/projects/EXAMPLE_PROJ/administrators?apiKey=dummy123456789apikey" | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   876  100   876    0     0   4200      0 --:--:-- --:--:-- --:--:--  4180
[
  {
    "id": 123456,
    "userId": "dummyUser1",
    "name": "山田太郎",
    "roleType": 2,
    "lang": "ja",
    "mailAddress": "yamada.taro@example.com",
    "nulabAccount": {
      "nulabId": "dummyNulabId123",
      "name": "山田太郎",
      "uniqueId": "t_yamada",
      "iconUrl": "https://apps.nulab.com/account/dummyAccountId1/photo/large?t=1234567890"
    },
    "keyword": "山田太郎 YAMADA TARO",
    "lastLoginTime": "2024-03-15T10:00:00Z"
  },
  {
    "id": 123457,
    "userId": "dummyUser2",
    "name": "鈴木花子",
    "roleType": 2,
    "lang": "ja",
    "mailAddress": "suzuki.hanako@example.com",
    "nulabAccount": {
      "nulabId": "dummyNulabId456",
      "name": "鈴木花子",
      "uniqueId": "h_suzuki",
      "iconUrl": "https://apps.nulab.com/account/dummyAccountId2/photo/large?t=1234567891"
    },
    "keyword": "鈴木花子 SUZUKI HANAKO",
    "lastLoginTime": "2024-03-16T11:00:00Z"
  }
]

複数のプロジェクトに対して実行する

複数のプロジェクトキーを配列に含めます。

project_keys=("DUMMY_PROJECT_1" "DUMMY_PROJECT_2")

for project_key in "${project_keys[@]}"; do
    curl "https://example.backlog.com/api/v2/projects/${project_key}/administrators?apiKey=dummy123456789apikey" | jq '.[] | {name: .name, mailAddress: .mailAddress}'
done

実行すると以下のように表示されます。

ダミー名1-3は同一のDUMMY_PROJECT_1プロジェクト、ダミー名4はDUMMY_PROJECT_2プロジェクトのプロジェクト管理者です。

$ project_keys=("DUMMY_PROJECT_1" "DUMMY_PROJECT_2")

for project_key in "${project_keys[@]}"; do
    curl "https://example.backlog.com/api/v2/projects/${project_key}/administrators?apiKey=dummy123456789apikey" | jq '.[] | {name: .name, mailAddress: .mailAddress}'
done

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1314  100  1314    0     0   3426      0 --:--:-- --:--:-- --:--:--  3421
{
  "name": "ダミー名1",
  "mailAddress": "dummy1@example.com"
}
{
  "name": "ダミー名2",
  "mailAddress": "dummy2@example.com"
}
{
  "name": "ダミー名3",
  "mailAddress": "dummy3@example.com"
}
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent   Left  Speed
100   463  100   463    0     0   2240      0 --:--:-- --:--:-- --:--:--  2247
{
  "name": "ダミー名4",
  "mailAddress": "dummy4@example.com"
}

スペース全体のプロジェクトに対して実行する

スペース全体のプロジェクト横断で確認したいときは別のAPIとの組み合わせが必要です。

プロジェクト一覧の応答を配列に格納します。

# プロジェクトキーを取得
project_keys=()
while IFS= read -r project_key; do
    project_keys+=("$project_key")
done < <(curl -s "https://example.backlog.com/api/v2/projects?apiKey=dummy123456789apikey" | jq -r '.[].projectKey')

# 各プロジェクトキーに対してループ
for project_key in "${project_keys[@]}"; do
    echo "Project Key: $project_key"
    curl -s "https://example.backlog.com/api/v2/projects/${project_key}/administrators?apiKey=dummy123456789apikey"  | jq '.[] | {name: .name, mailAddress: .mailAddress}'
done

実行すると次のとおりになります。

$ project_keys=()
while IFS= read -r project_key; do
    project_keys+=("$project_key")
done

$ for project_key in "${project_keys[@]}"; do
    echo "Project Key: $project_key"
    curl -s "https://example.backlog.com/api/v2/projects/${project_key}/administrators?apiKey=dummy123456789apikey"  | jq '.[] | {name: .name, mailAddress: .mailAddress}'
done

Project Key: ダミープロジェクトキー1
{
  "name": "ダミー名1",
  "mailAddress": "dummy1@example.com"
}
Project Key: ダミープロジェクトキー2
{
  "name": "ダミー名2",
  "mailAddress": "dummy2@example.com"
}
{
  "name": "ダミー名3",
  "mailAddress": "dummy3@example.com"
}
{
  "name": "ダミー名4",
  "mailAddress": "dummy4@example.com"
}
Project Key: ダミープロジェクトキー3
Project Key: ダミープロジェクトキー4

curlだと1度に実行できないので、1度に実行するにはプログラミングの知識が必要になってきます。

Python 3.13.0 で動く形に置き換えると次のような形式になります。

Backlog APIにはレート制限という一定時間に一定回数以上の処理を行う方に対して、

制限を施す仕組みがあります。レート制限を考慮した形にしています。

import requests
import time

api_key = 'dummy123456789apikey'
base_url = 'https://example.backlog.com/api/v2'

# プロジェクトキーを取得
response = requests.get(f"{base_url}/projects?apiKey={api_key}")
project_keys = [project['projectKey'] for project in response.json()]

# 各プロジェクトキーに対してループ
for project_key in project_keys:
    print(f"Project Key: {project_key}")
    
    # レート制限を考慮してリクエストを送信
    while True:
        response = requests.get(f"{base_url}/projects/{project_key}/administrators?apiKey={api_key}")
        
        if response.status_code == 429:  # レート制限に達した場合
            reset_time = int(response.headers.get('X-RateLimit-Reset', time.time() + 60))
            wait_time = max(0, reset_time - int(time.time())) + 1  # 1秒待機
            print(f"Rate limit exceeded. Waiting for {wait_time} seconds...")
            time.sleep(wait_time)
            continue  # 再試行
        else:
            break  # 成功した場合はループを抜ける

    administrators = response.json()
    for admin in administrators:
        print({'name': admin['name'], 'mailAddress': admin['mailAddress']})

Pythonは一例で他のプログラミング言語でも可能です。

こちらには今回のAPIとは異なりますが、他のプログラミング言語の例の記載があります。

まとめ

いかがでしたでしょうか。

プロジェクト管理者はメンバーに対して、個別に権限を付与していく中で、

プロジェクトが多くなると管理が煩雑になる可能性があります。

そういったときに、このようにBacklog APIを活用することで、

Webブラウザでそれぞれのプロジェクトを表示して確認する手間を省くことができます。

こちらのブログがどなたかの参考になれば幸いです。

その他

Backlogのユーザグループである「JBUG」(じぇいばぐ)による1年に1度の大きなイベント、

「Backlog World 2024」が横浜・パシフィコ横浜で12月14日行われます。

私も前日に佐賀から横浜へ入りイベント当日はフルに参加する予定です。

まだ、このブログを公開する12月7日では受付募集中ですのでお申し込みいただき、

当日会場でお声がけいただければ嬉しいです。