🐍

Issueに紐づくGitHub Projectsの情報をGraphQL経由で取得する

2023/03/29に公開

小ネタです🍣

Issueに紐づくGitHub Projectsを情報を取得するスクリプトをChatGPTに教えてもらったので共有します

例えば、取得したいProjectに以下のようなCustom fieldsがあった場合、

以下のようなスクリプトで対象のIssueに紐づく内容が取得できます

fieldValueByName の戻り値について、どのようなデータ型を選択すべきかについては、以下を確認してください

https://docs.github.com/ja/graphql/reference/unions#projectv2itemfieldvalue

get_projects_by_issue_number.py
import csv
import json
import os
import sys

import requests

query = """
query($owner: String!, $repo: String!, $issueNumber: Int!) {
  repository(owner: $owner, name: $repo) {
    issue(number: $issueNumber) {
      number
      title
      state
      closedAt
      projectItems(first: 10) {
        totalCount
        nodes {
            project {
                number
                title
            }
            status: fieldValueByName(name: "Status") {
                ... on ProjectV2ItemFieldSingleSelectValue {
                    name
                }
            }
            iteration: fieldValueByName(name: "Iteration") {
                ... on ProjectV2ItemFieldIterationValue {
                    title
                    startDate
                    duration
                }
            }
            storyType: fieldValueByName(name: "Story Type") {
                ... on ProjectV2ItemFieldSingleSelectValue {
                    name
                }
            }
            storyPoint: fieldValueByName(name: "Story Point") {
                ... on ProjectV2ItemFieldNumberValue {
                    number
                }
            }
            from: fieldValueByName(name: "From") {
                ... on ProjectV2ItemFieldSingleSelectValue {
                    name
                }
            }
        }
      }
    }
  }
}
"""


writer = csv.writer(sys.stdout, delimiter='\t')


def fetch_issue(owner: str, repo: str, issue_number: int) -> None:
    headers = {
        "Authorization": f"Bearer {os.environ['GITHUB_TOKEN']}"
    }

    response = requests.post(
        "https://api.github.com/graphql",
        headers=headers,
        json={
            "query": query,
            "variables": {
                "owner": owner,
                "repo": repo,
                "issueNumber": issue_number,
            }
        }
    )

    response.raise_for_status()
    if not response.json().get('data'):
        raise Exception(json.dumps(response.json()))
    else:
        data = response.json()['data']

        for project_item in data['repository']['issue']['projectItems']['nodes']:
            writer.writerow([
                owner,
                repo,
                issue_number,
                data['repository']['issue']['title'],
                data['repository']['issue']['state'],
                data['repository']['issue']['closedAt'],
                project_item['project']['number'],
                project_item['project']['title'],
                project_item['iteration']['title'] if project_item['iteration'] else None,
                project_item['iteration']['startDate'] if project_item['iteration'] else None,
                project_item['iteration']['duration'] if project_item['iteration'] else None,
                project_item['storyType']['name'] if project_item['storyType'] else None,
                project_item['storyPoint']['number'] if project_item['storyPoint'] else None,
                project_item['from']['name'] if project_item['from'] else None,
            ])


owner = sys.argv[1]
repo = sys.argv[2]
issue_numbers = map(int, sys.argv[3].split(','))

writer.writerow([
    'owner',
    'repo',
    'issue_number',
    'title',
    'state',
    'closed_at',
    'project_number',
    'project_title',
    'iteration',
    'iteration_startDate',
    'iteration_duration',
    'story_type',
    'story_point',
    'from',
])

for issue_number in map(int, sys.argv[3].split(',')):
    fetch_issue(owner=owner, repo=repo, issue_number=issue_number)

実行イメージは以下です
実行時に、 GITHUB_TOKEN にPATを設定してください

$ python ./get_projects_by_issue_number owner repo "18101"
owner   repo    issue_number    title   state   closed_at       project_number  project_title   iteration       iteration_startDate     iteration_duration      story_type      story_point     from
owner      repo  18101   tflintの導入    OPEN            13      SR Agile Board  Iteration 6     2023-03-24      14      🚸 Unplanned    1.0

そんだけ😌

もしも仕様が期待するものと違ったり、バグがあった場合はChatGPTになおしてもらってください

Discussion