TaskSphere:GitHub プロジェクトの情報を取得・更新する Python スクリプト

AI

はじめに

このPythonスクリプトは、GitHub APIを使用してGitHubプロジェクトの情報を取得し、プロジェクトアイテムのフィールド値を更新することができます。初心者の方でも、このスクリプトを使ってGitHubプロジェクトを管理することができるでしょう。

必要な環境変数

スクリプトを実行する前に、以下の環境変数を設定する必要があります。

  • GITHUB_PERSONAL_ACCESS_TOKEN: GitHubのパーソナルアクセストークン
  • GITHUB_USER_LOGIN: GitHubのユーザーログイン名
  • GITHUB_PROJECT_NUMBER: 対象のGitHubプロジェクト番号

これらの環境変数が正しく設定されていない場合、スクリプトは実行されません。

スクリプトの概要

このスクリプトは以下の機能を持っています。

  1. 指定されたGitHubプロジェクトの情報を取得する
  2. プロジェクトのアイテム(Issue, PullRequest, DraftIssue)の詳細を取得する
  3. プロジェクトのフィールド情報を取得する
  4. 指定されたアイテムのフィールド値を更新する

コードの解説

必要なライブラリのインポート

import os
import requests
from termcolor import colored
from art import *
  • os: 環境変数の取得に使用
  • requests: GitHub APIへのHTTPリクエストに使用
  • termcolor: 出力テキストの色付けに使用
  • art: スクリプト名のアスキーアートの出力に使用

環境変数の取得

token = os.environ.get("GITHUB_PERSONAL_ACCESS_TOKEN")
user_login = os.environ.get("GITHUB_USER_LOGIN")
project_number = os.environ.get("GITHUB_PROJECT_NUMBER")
  • 必要な環境変数を取得します。

環境変数の検証

def validate_environment_variables():
    if token is None or user_login is None or project_number is None:
        print("Error: Required environment variables are not set.")
        exit(1)
  • 環境変数が正しく設定されているかを検証します。
  • 設定されていない場合はエラーメッセージを表示し、スクリプトを終了します。

プロジェクト情報の取得

def get_project_info():
    query_project = """
    query {
      user(login: "USER_LOGIN") {
        projectV2(number: NUMBER) {
          title
          id
        }
      }
    }
    """
    query_project = query_project.replace("USER_LOGIN", user_login)
    query_project = query_project.replace("NUMBER", project_number)

    data_project = {
        "query": query_project
    }

    response_project = requests.post("https://api.github.com/graphql", headers=headers, json=data_project)

    if "errors" in response_project.json():
        print(f"Error: {response_project.json()['errors'][0]['message']}")
        exit(1)

    project_title = response_project.json()["data"]["user"]["projectV2"]["title"]
    project_id = response_project.json()["data"]["user"]["projectV2"]["id"]

    print(colored(f"Project Title: {project_title}", "green"))
    print(colored(f"Project ID: {project_id}", "cyan"))

    return project_id
  • GraphQL クエリを使用して、指定されたユーザーとプロジェクト番号に基づいてプロジェクト情報を取得します。
  • プロジェクトのタイトルとIDを取得し、色付きで出力します。
  • プロジェクトIDを返します。

プロジェクトアイテムの取得

def get_project_items(project_id):
    query_items = """
    query {
      node(id: "PROJECT_ID") {
        ... on ProjectV2 {
          items(first: 20) {
            nodes {
              id
              content {
                ... on DraftIssue {
                  title
                  body
                }
                ... on Issue {
                  title
                  number
                  assignees(first: 10) {
                    nodes {
                      login
                    }
                  }
                }
                ... on PullRequest {
                  title
                  number
                  assignees(first: 10) {
                    nodes {
                      login
                    }
                  }
                }
              }
            }
          }
          fields(first: 20) {
            nodes {
              ... on ProjectV2Field {
                id
                name
              }
              ... on ProjectV2IterationField {
                id
                name
                configuration {
                  iterations {
                    startDate
                    id
                  }
                }
              }
              ... on ProjectV2SingleSelectField {
                id
                name
                options {
                  id
                  name
                }
              }
            }
          }
        }
      }
    }
    """
    query_items = query_items.replace("PROJECT_ID", project_id)

    data_items = {
        "query": query_items
    }

    response_items = requests.post("https://api.github.com/graphql", headers=headers, json=data_items)

    if "errors" in response_items.json():
        print(f"Error: {response_items.json()['errors'][0]['message']}")
        exit(1)

    items = response_items.json()["data"]["node"]["items"]["nodes"]
    fields = response_items.json()["data"]["node"]["fields"]["nodes"]

    print("---------------------------")
    print(colored("Items:", "magenta"))
    for item in items:
        print(colored(f"Item ID: {item['id']}", "cyan"))

        content = item["content"]
        if "title" in content:
            print(colored(f"Title: {content['title']}", "green"))
        if "body" in content:
            print(colored(f"Body: {content['body']}", "green"))
        if "number" in content:
            print(colored(f"Number: {content['number']}", "green"))

            # Get the node_id for the issue or pull request
            if "Issue" in content["__typename"]:
                node_id = requests.get(f"https://api.github.com/repos/{user_login}/{repo_name}/issues/{content['number']}", headers=headers).json()["node_id"]
            elif "PullRequest" in content["__typename"]:
                node_id = requests.get(f"https://api.github.com/repos/{user_login}/{repo_name}/pulls/{content['number']}", headers=headers).json()["node_id"]

            print(colored(f"Node ID: {node_id}", "cyan"))

        if "assignees" in content:
            assignees = [assignee["login"] for assignee in content["assignees"]["nodes"]]
            print(colored(f"Assignees: {', '.join(assignees)}", "green"))

        print("---")

    print("---------------------------")
    print(colored("Fields:", "magenta"))
    for field in fields:
        print(colored(f"Field ID: {field['id']}", "cyan"))
        print(colored(f"Field Name: {field['name']}", "green"))

        if "configuration" in field:
            iterations = field["configuration"]["iterations"]
            for iteration in iterations:
                print(colored(f"Iteration ID: {iteration['id']}", "cyan"))
                print(colored(f"Iteration Start Date: {iteration['startDate']}", "green"))

        if "options" in field:
            options = field["options"]
            for option in options:
                print(colored(f"Option ID: {option['id']}", "cyan"))
                print(colored(f"Option Name: {option['name']}", "green"))

        print("---")
  • GraphQL クエリを使用して、指定されたプロジェクトIDに基づいてプロジェクトアイテムとフィールド情報を取得します。
  • 各アイテムについて、タイトル、本文、番号、担当者などの詳細を取得し、色付きで出力します。
  • 各フィールドについて、ID、名前、反復情報、オプション情報などを取得し、色付きで出力します。

アイテムのフィールド値の更新

def update_item_field_value(project_id, item_id, field_id, field_type, field_value):
    mutation_update_field = """
    mutation {
      updateProjectV2ItemFieldValue(
        input: {
          projectId: "PROJECT_ID"
          itemId: "ITEM_ID"
          fieldId: "FIELD_ID"
          value: {
            FIELD_TYPE: FIELD_VALUE
          }
        }
      ) {
        projectV2Item {
          id
        }
      }
    }
    """
    mutation_update_field = mutation_update_field.replace("PROJECT_ID", project_id)
    mutation_update_field = mutation_update_field.replace("ITEM_ID", item_id)
    mutation_update_field = mutation_update_field.replace("FIELD_ID", field_id)
    mutation_update_field = mutation_update_field.replace("FIELD_TYPE", field_type)
    mutation_update_field = mutation_update_field.replace("FIELD_VALUE", field_value)

    data_update_field = {
        "query": mutation_update_field
    }

    response_update_field = requests.post("https://api.github.com/graphql", headers=headers, json=data_update_field)

    if "errors" in response_update_field.json():
        print(f"Error: {response_update_field.json()['errors'][0]['message']}")
    else:
        updated_item_id = response_update_field.json()["data"]["updateProjectV2ItemFieldValue"]["projectV2Item"]["id"]
        print(colored(f"Updated item field with ID: {updated_item_id}", "green"))
  • GraphQL ミューテーションを使用して、指定されたプロジェクトID、アイテムID、フィールドID、フィールドタイプ、フィールド値に基づいてアイテムのフィールド値を更新します。
  • 更新が成功した場合、更新されたアイテムのIDを色付きで出力します。
  • エラーが発生した場合は、エラーメッセージを出力します。

メイン処理

if __name__ == "__main__":
    validate_environment_variables()

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }

    project_id = get_project_info()
    get_project_items(project_id)

    item_id = input("Enter the ID of the item to update: ")
    field_id = input("Enter the ID of the field to update: ")
    field_type = input("Enter the type of the field (text, number, date): ")

    if field_type == "text":
        field_value = f'"{input("Enter the new text value: ")}"'
    elif field_type == "number":
        field_value = input("Enter the new number value: ")
    elif field_type == "date":
        field_value = f'"{input("Enter the new date value (YYYY-MM-DD): ")}"'
    else:
        print("Invalid field type.")
        exit(1)

    update_item_field_value(project_id, item_id, field_id, field_type, field_value)
  • validate_environment_variables() を呼び出して、必要な環境変数が設定されているかを検証します。
  • HTTPリクエストのヘッダーを設定します。
  • get_project_info() を呼び出して、プロジェクト情報を取得します。
  • get_project_items(project_id) を呼び出して、プロジェクトのアイテムとフィールド情報を取得します。
  • ユーザーに更新するアイテムのID、フィールドのID、フィールドのタイプ、新しいフィールド値を入力するよう求めます。
  • update_item_field_value() を呼び出して、指定されたアイテムのフィールド値を更新します。

まとめ

このPythonスクリプトを使用することで、GitHub APIを介してGitHubプロジェクトの情報を取得し、プロジェクトアイテムのフィールド値を更新することができます。初心者の方でも、このスクリプトを理解し、活用することができるでしょう。

GitHubプロジェクトの管理を自動化し、効率化するために、ぜひこのスクリプトを活用してみてください。

リポジトリ

GitHub - Sunwood-ai-labs/TaskSphere
Contribute to Sunwood-ai-labs/TaskSphere development by creating an account on GitHub.

参考サイト

API を使用して Projects を管理する - GitHub Docs
GraphQL API を使用して、プロジェクトを自動化できます。
GitHub GraphQL APIを利用し、複数リポジトリが紐づくGitHub ProjectsのIssueリストを取得する - いいものを広め隊
はじめに 今回想定するGitHub Projects GitHub GraphQL APIを使うまでの準備 1. アクセストークンの登録 2. Issueを取得したいGitHub Projectsのidを取得する 今回はPythonで実行します GitHub Projectsに紐づくIssue一覧を取得する 特定のステ...
個人用アクセス トークンを管理する - GitHub Docs
コマンド ラインまたは API を使用して GitHub への認証を行うときに、パスワードの代わりに personal access token を使用することができます。

コメント

タイトルとURLをコピーしました