Pivotal Tracker APIですべてのストーリーを取得する

Pivotal Tracker API ですべてのストーリーを取得してみました。
2024.03.23

Pivotal Tracker API ですべてのストーリーを取得してみました。

おすすめの方

  • Pivotal Tracker APIを利用したい方
  • Pivotal Tracker APIですべてのストーリーを取得したい方

適当なプロジェクトを用意する

01_pivotal_tracker

すべてのストーリーを取得するスクリプト

次のAPIを利用します。

レスポンスヘッダーに総数(X-Tracker-Pagination-Total)があるので、ループして取得しています。

app.py

import requests
import urllib.parse

API_ENDPOINT = "https://www.pivotaltracker.com/services/v5"
TOKEN = "xxx"

PROJECT_ID = xxx


def main():
    stories = get_stories(PROJECT_ID)
    print(f"len: {len(stories)}")

    for story in stories:
        print(f"{story['id']}, {story['current_state']}, {story['story_type']}")


def get_headers():
    return {
        "X-TrackerToken": TOKEN,
        "Content-Type": "application/json",
    }


def get_stories(project_id, query=""):
    items = []
    offset = 0
    limit = 3  # 確実にloopさせるため、小さな値にしている

    while True:
        param = f"limit={limit}&offset={offset}{query}"
        url_param = urllib.parse.quote(param, safe="=&")

        resp = requests.get(
            f"{API_ENDPOINT}/projects/{project_id}/stories?{url_param}",
            headers=get_headers(),
        )

        items += resp.json()
        total = int(resp.headers["X-Tracker-Pagination-Total"])

        if total < offset:
            break
        offset += limit
    return items


if __name__ == "__main__":
    main()

スクリプトの実行結果

len: 14
176010434, accepted, feature
176008582, accepted, chore
182876336, started, feature
176030987, unstarted, feature
176008289, unstarted, feature
176010184, unstarted, chore
176010501, unstarted, release
183803436, unstarted, bug
176010180, unstarted, chore
176010439, unstarted, feature
176030010, unscheduled, release
176030204, unscheduled, chore
183803428, unscheduled, feature
183803446, unscheduled, bug

取得できるデータ

何もしなければ、ひとつのストーリーについて、次のようなデータを取得できます。

{
    "kind": "story",
    "id": 176008289,
    "created_at": "2020-12-04T08:37:37Z",
    "updated_at": "2024-03-19T10:30:24Z",
    "estimate": 3,
    "story_type": "feature",
    "story_priority": "p3",
    "name": "買い物客は、商品一覧ページに1秒未満で遷移したい。なぜなら検索が遅いと購入する気が無くなるからだ。",
    "description": "xxx",
    "current_state": "unstarted",
    "requested_by_id": 222,
    "url": "https://www.pivotaltracker.com/story/show/176008289",
    "project_id": 111,
    "owner_ids": [
        222
    ],
    "labels": [
        {
            "id": 22780542,
            "project_id": 111,
            "kind": "label",
            "name": "ready",
            "created_at": "2020-12-04T08:49:23Z",
            "updated_at": "2020-12-04T08:49:23Z"
        },
        {
            "id": 24407832,
            "project_id": 111,
            "kind": "label",
            "name": "これはエピックです",
            "created_at": "2024-03-19T10:30:12Z",
            "updated_at": "2024-03-19T10:30:12Z"
        },
        {
            "id": 24407829,
            "project_id": 111,
            "kind": "label",
            "name": "機能a",
            "created_at": "2024-03-19T10:17:02Z",
            "updated_at": "2024-03-19T10:17:02Z"
        }
    ],
    "owned_by_id": 222
}

コメント、プルリクエスト、タスク、作成者、対応者を取得する

通常では取得できない項目でも、fieldsでストーリのプロパティを指定すれば取得できます。

app.py

    stories = get_stories(
        PROJECT_ID,
        "&fields=comments,pull_requests,tasks,requested_by,owners",
    )
{
  "id": 176008289,
  "requested_by": {
    "kind": "person",
    "id": 222,
    "name": "fujiigenki",
    "email": "sample@example.com",
    "initials": "fu",
    "username": "fujiigenki"
  },
  "owners": [
    {
      "kind": "person",
      "id": 222,
      "name": "fujiigenki",
      "email": "sample@example.com",
      "initials": "fu",
      "username": "fujiigenki"
    }
  ],
  "tasks": [
    {
      "id": 77037287,
      "kind": "task",
      "description": "アレをコレしてソレする",
      "complete": false,
      "story_id": 176008289,
      "position": 1,
      "created_at": "2023-08-01T10:26:10Z",
      "updated_at": "2023-08-01T10:26:10Z"
    }
  ],
  "pull_requests": [
    {
      "id": 2856696,
      "kind": "pull_request",
      "story_id": 176008289,
      "owner": "xxx",
      "repo": "repo-name",
      "host_url": "https://github.com/",
      "original_url": "https://github.com/xxx/repo-name/pull/49",
      "status": "unknown",
      "number": 49,
      "created_at": "2024-03-23T04:50:23Z",
      "updated_at": "2024-03-23T04:50:23Z"
    }
  ],
  "comments": [
    {
      "kind": "comment",
      "id": 220233704,
      "text": "不具合が見つかった",
      "person_id": 222,
      "created_at": "2020-12-04T10:45:39Z",
      "updated_at": "2020-12-04T10:45:39Z",
      "story_id": 176008289
    },
    {
      "kind": "comment",
      "id": 220858363,
      "text": "A案とB案があるけど、B案になっった\n- https://slack.com/...",
      "person_id": 222,
      "created_at": "2021-01-04T07:48:59Z",
      "updated_at": "2021-01-04T07:49:22Z",
      "story_id": 176008289
    }
  ]
}

参考