Skip to main content

プロジェクト(ベータ)の自動化

組み込みのワークフロー、あるいはAPIとGitHub Actionsを使ってプロジェクトを管理できます。

Note: Projects (beta) is currently in public beta and subject to change.

はじめに

プロジェクトの管理に役立つ自動化を追加できます。 プロジェクト(ベータ)には、UIを通じて設定できる組み込みのワークフローが含まれています。 加えて、GraphQL APIとGitHub Actionsでカスタムのワークフローを書くことができます。

組み込みのワークフロー

Projects (beta) includes built-in workflows that you can use to update the Status of items based on certain events. For example, you can automatically set the status to Todo when an item is added to your project or set the status to Done when an issue is closed.

When your project initializes, two workflows are enabled by default: When issues or pull requests in your project are closed, their status is set to Done, and when pull requests in your project are merged, their status is set to Done.

プロジェクトでは、組み込みのワークフローを有効化あるいは無効化できます。

  1. プロジェクトにアクセスします。
  2. In the top-right, click to open the menu.
  3. In the menu, click Workflows.
  4. Under Default workflows, click on the workflow that you want to edit.
  5. If the workflow can apply to both issues and pull requests, next to When, check the item type(s) that you want to act on.
  6. Next to Set, choose the value that you want to set the status to.
  7. If the workflow is disabled, click the toggle next to Disabled to enable the workflow.

GitHub Actionsのワークフロー

このセクションでは、GraphQL APIとGitHub Actionsを使ってOrganizationのプロジェクトにPull Requestを追加する方法を紹介します。 このワークフローの例では、Pull Requestが"ready for review"としてマークされると、プロジェクトに新しいタスクが追加され、"Status"フィールドが"Todo"に設定され、現在の日付がカスタムの"Date posted"フィールドに追加されます。

必要に応じて、以下のワークフローの1つをコピーして、以下の表にあるように変更できます。

プロジェクトは複数のリポジトリにまたがることができますが、ワークフローは1つのリポジトリに固有です。 ワークフローを、プロジェクトに追跡させたいそれぞれのリポジトリに追加してください。 ワークフローファイルの作成に関する詳しい情報については「GitHub Actionsのクイックスタート」を参照してください。

この記事は、GitHub Actionsを基本的に理解していることを前提としています。 GitHub Actionsに関する詳しい情報については「GitHub Actions 」を参照してください。

APIを通じてプロジェクトに対して行える他の変更に関する情報については「APIを使ったプロジェクトの管理」を参照してください。

ノート: GITHUB_TOKENはリポジトリレベルをスコープとしており、プロジェクト(ベータ)にはアクセスできません。 プロジェクト(ベータ)にアクセスするには、GitHub App(Organizationプロジェクトの場合に推奨)もしくは個人アクセストークン(ユーザプロジェクトの場合に推奨)を作成できます。 以下には、どちらの方法のワークフローの例も示します。

GitHub Appで認証を行うワークフローの例

  1. GitHub Appを作成するか、自分のOrganizationが所有する既存のGitHub Appを選択してください。 詳しい情報については「GitHub Appの作成」を参照してください。

  2. GitHub Appに、Organizationプロジェクトに対する読み込み及び書き込み権限を与えてください。 詳しい除法については「GitHub Appの権限の編集」を参照してください。

    ノート: アプリケーションのOrganizationプロジェクトに対する権限と、リポジトリプロジェクトに対する権限を制御できます。 Organizationプロジェクトに対する読み書き権限を与えなければなりません。リポジトリプロジェクトに対する読み書き権限だけでは不十分です。

  3. OrganizationにGitHub Appをインストールしてください。 プロジェクトがアクセスする必要があるすべてのリポジトリにインストールしてください。 詳しい情報については「GitHub Appsのインストール」を参照してください。

  4. GitHub AppのIDを、リポジトリもしくはOrganizationのシークレットとして保存してください。 以下のワークフローでは、APP_IDをシークレット名に置き換えてください。 アプリケーションIDは、アプリケーションの設定ページで、あるいはアプリケーションのAPIを通じて確認できます。 詳しい情報については「アプリケーション」を参照してください。

  5. アプリケーションの秘密鍵を生成してください。 作成されたファイルの内容を、シークレットとしてリポジトリもしくはOrganizationに保存してください。 (ファイルの内容は、-----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY-----という部分も含めて全体をほぞんしてください。) 以下のワークフローでは、APP_PEMをシークレットの名前に置き換えてください。 詳しい情報については「GitHub Appsでの認証」を参照してください。

  6. 以下のワークフローでは、YOUR_ORGANIZATIONをOrganizationの名前で置き換えてください。 たとえばocto-orgというようにします。 YOUR_PROJECT_NUMBERは、プロジェクトの番号で置き換えてください。 プロジェクト番号を知るには、プロジェクトのURLを見てください。 たとえばhttps://github.com/orgs/octo-org/projects/5ではプロジェクト番号は5です。

YAML
# このワークフローはGitHubによって認定されていないアクションを使用します。
# それらはサードパーティによって提供され、
# 別個の利用規約、プライバシーポリシー、
# サポートドキュメンテーションが適用されます。

name: Add PR to project
on:
  pull_request:
    types:
      - ready_for_review
jobs:
  track_pr:
    runs-on: ubuntu-latest
    steps:
      - name: Generate token
        id: generate_token
        uses: tibdex/github-app-token@36464acb844fc53b9b8b2401da68844f6b05ebb0
        with:
          app_id: ${{ secrets.APP_ID }}
          private_key: ${{ secrets.APP_PEM }}

      - name: Get project data
        env:
          GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
          ORGANIZATION: YOUR_ORGANIZATION
          PROJECT_NUMBER: YOUR_PROJECT_NUMBER
        run: |
          gh api graphql -f query='
            query($org: String!, $number: Int!) {
              organization(login: $org){
                projectNext(number: $number) {
                  id
                  fields(first:20) {
                    nodes {
                      id
                      name
                      settings
                    }
                  }
                }
              }
            }' -f org=$ORGANIZATION -F number=$PROJECT_NUMBER > project_data.json

          echo 'PROJECT_ID='$(jq '.data.organization.projectNext.id' project_data.json) >> $GITHUB_ENV
          echo 'DATE_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Date posted") | .id' project_data.json) >> $GITHUB_ENV
          echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV
          echo 'TODO_OPTION_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") |.settings | fromjson.options[] | select(.name=="Todo") |.id' project_data.json) >> $GITHUB_ENV

      - name: Add PR to project
        env:
          GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
          PR_ID: ${{ github.event.pull_request.node_id }}
        run: |
          item_id="$( gh api graphql -f query='
            mutation($project:ID!, $pr:ID!) {
              addProjectNextItem(input: {projectId: $project, contentId: $pr}) {
                projectNextItem {
                  id
                }
              }
            }' -f project=$PROJECT_ID -f pr=$PR_ID --jq '.data.addProjectNextItem.projectNextItem.id')"

          echo 'ITEM_ID='$item_id >> $GITHUB_ENV

      - name: Get date
        run: echo "DATE=$(date +"%Y-%m-%d")" >> $GITHUB_ENV

      - name: Set fields
        env:
          GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
        run: |
          gh api graphql -f query='
            mutation (
              $project: ID!
              $item: ID!
              $status_field: ID!
              $status_value: String!
              $date_field: ID!
              $date_value: String!
            ) {
              set_status: updateProjectNextItemField(input: {
                projectId: $project
                itemId: $item
                fieldId: $status_field
                value: $status_value
              }) {
                projectNextItem {
                  id
                  }
              }
              set_date_posted: updateProjectNextItemField(input: {
                projectId: $project
                itemId: $item
                fieldId: $date_field
                value: $date_value
              }) {
                projectNextItem {
                  id
                }
              }
            }' -f project=$PROJECT_ID -f item=$ITEM_ID -f status_field=$STATUS_FIELD_ID -f status_value=${{ env.TODO_OPTION_ID }} -f date_field=$DATE_FIELD_ID -f date_value=$DATE --silent

個人アクセストークンで認証するワークフローの例

  1. org:write スコープを使用して個人アクセストークンを作成します。 詳しい情報については、「個人アクセストークンを作成する」を参照してください。
  2. この個人アクセストークンをシークレットとしてリポジトリもしくはOrganizationに保存します。
  3. 以下のワークフローでは、YOUR_TOKENをそのシークレットの名前で置き換えてください。 YOUR_ORGANIZATIONをOrganizationの名前で置き換えてください。 たとえばocto-orgというようにします。 YOUR_PROJECT_NUMBERは、プロジェクトの番号で置き換えてください。 プロジェクト番号を知るには、プロジェクトのURLを見てください。 たとえばhttps://github.com/orgs/octo-org/projects/5ではプロジェクト番号は5です。
YAML
name: Add PR to project
on:
  pull_request:
    types:
      - ready_for_review
jobs:
  track_pr:
    runs-on: ubuntu-latest
    steps:
      - name: Get project data
        env:
          GITHUB_TOKEN: ${{ secrets.YOUR_TOKEN }}
          ORGANIZATION: YOUR_ORGANIZATION
          PROJECT_NUMBER: YOUR_PROJECT_NUMBER
        run: |
          gh api graphql -f query='
            query($org: String!, $number: Int!) {
              organization(login: $org){
                projectNext(number: $number) {
                  id
                  fields(first:20) {
                    nodes {
                      id
                      name
                      settings
                    }
                  }
                }
              }
            }' -f org=$ORGANIZATION -F number=$PROJECT_NUMBER > project_data.json

          echo 'PROJECT_ID='$(jq '.data.organization.projectNext.id' project_data.json) >> $GITHUB_ENV
          echo 'DATE_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Date posted") | .id' project_data.json) >> $GITHUB_ENV
          echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV
          echo 'TODO_OPTION_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") |.settings | fromjson.options[] | select(.name=="Todo") |.id' project_data.json) >> $GITHUB_ENV

      - name: Add PR to project
        env:
          GITHUB_TOKEN: ${{ secrets.YOUR_TOKEN }}
          PR_ID: ${{ github.event.pull_request.node_id }}
        run: |
          item_id="$( gh api graphql -f query='
            mutation($project:ID!, $pr:ID!) {
              addProjectNextItem(input: {projectId: $project, contentId: $pr}) {
                projectNextItem {
                  id
                }
              }
            }' -f project=$PROJECT_ID -f pr=$PR_ID --jq '.data.addProjectNextItem.projectNextItem.id')"

          echo 'ITEM_ID='$item_id >> $GITHUB_ENV

      - name: Get date
        run: echo "DATE=$(date +"%Y-%m-%d")" >> $GITHUB_ENV

      - name: Set fields
        env:
          GITHUB_TOKEN: ${{ secrets.YOUR_TOKEN }}
        run: |
          gh api graphql -f query='
            mutation (
              $project: ID!
              $item: ID!
              $status_field: ID!
              $status_value: String!
              $date_field: ID!
              $date_value: String!
            ) {
              set_status: updateProjectNextItemField(input: {
                projectId: $project
                itemId: $item
                fieldId: $status_field
                value: $status_value
              }) {
                projectNextItem {
                  id
                  }
              }
              set_date_posted: updateProjectNextItemField(input: {
                projectId: $project
                itemId: $item
                fieldId: $date_field
                value: $date_value
              }) {
                projectNextItem {
                  id
                }
              }
            }' -f project=$PROJECT_ID -f item=$ITEM_ID -f status_field=$STATUS_FIELD_ID -f status_value=${{ env.TODO_OPTION_ID }} -f date_field=$DATE_FIELD_ID -f date_value=$DATE --silent

ワークフローの説明

以下の表は、ワークフローの例のセクションについて説明しており、自分の利用方法にそれらのワークフローを適応させる方法を示します。

on:
  pull_request:
    types:
      - ready_for_review
このワークフローは、リポジトリ内のPull Requestが"ready for review"としてマークされたときに実行されます。

GitHub App only:

- name: Generate token
  id: generate_token
  uses: tibdex/github-app-token@36464acb844fc53b9b8b2401da68844f6b05ebb0
  with:
    app_id: ${{ secrets.APP_ID }}
    private_key: ${{ secrets.APP_PEM }}
tibdex/github-app-token actionを使い、アプリケーションIDと秘密鍵からアプリケーション用のインストールアクセストークンを生成します。 このインストールアクセストークンは、後にワークフロー内で${{ steps.generate_token.outputs.token }}としてアクセスされます。

APP_IDはアプリケーションIDを含むシークレットの名前で置き換えてください。

APP_PEMは、アプリケーションの秘密鍵を含むシークレットの名前で置き換えてください。

GitHub App:

env:
  GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
  ORGANIZATION: YOUR_ORGANIZATION
  PROJECT_NUMBER: YOUR_PROJECT_NUMBER

Personal access token:

env:
  GITHUB_TOKEN: ${{ secrets.YOUR_TOKEN }}
  ORGANIZATION: YOUR_ORGANIZATION
  PROJECT_NUMBER: YOUR_PROJECT_NUMBER
このステップのための環境変数を設定します。

個人アクセストークンを使っているなら、YOUR_TOKENを個人アクセストークンを含むシークレットの名前で置き換えてください。

YOUR_ORGANIZATIONをOrganization名で置き換えてください。 たとえばocto-orgというようにします。

YOUR_PROJECT_NUMBERをプロジェクト番号で置き換えてください。 プロジェクト番号を知るには、プロジェクトのURLを見てください。 たとえばhttps://github.com/orgs/octo-org/projects/5ではプロジェクト番号は5です。
gh api graphql -f query='
  query($org: String!, $number: Int!) {
    organization(login: $org){
      projectNext(number: $number) {
        id
        fields(first:20) {
          nodes {
            id
            name
            settings
          }
        }
      }
    }
  }' -f org=$ORGANIZATION -F number=$PROJECT_NUMBER > project_data.json
GitHub CLIを使って、プロジェクトのIDと、プロジェクトの最初の20個のフィールドのID、名前、設定を、APIに問い合わせます。 レスポンスはproject_data.jsonというファイルに保存されます。
echo 'PROJECT_ID='$(jq '.data.organization.projectNext.id' project_data.json) >> $GITHUB_ENV
echo 'DATE_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Date posted") | .id' project_data.json) >> $GITHUB_ENV
echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV
echo 'TODO_OPTION_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Status") |.settings | fromjson.options[] | select(.name=="Todo") |.id' project_data.json) >> $GITHUB_ENV
APIクエリからのレスポンスをパースし、関連するIDを環境変数として保存します。 これを変更して、様々なフィールドやオプションのIDを取得してください。 例:
  • TeamというフィールドのIDを取得するには、echo 'TEAM_FIELD_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Team") | .id' project_data.json) >> $GITHUB_ENVを追加してください。
  • TeamフィールドのOctoteamというオプションのIDを取得するには、echo 'OCTOTEAM_OPTION_ID='$(jq '.data.organization.projectNext.fields.nodes[] | select(.name== "Team") |.settings | fromjson.options[] | select(.name=="Octoteam") |.id' project_data.json) >> $GITHUB_ENVを追加してください。
ノート: このワークフローは、プロジェクトが"Todo"というオプションを含む"Status"という単一選択フィールドと"Date posted"という日付フィールドを持つことを前提としています。 テーブル中にあるフィールドにマッチするよう、このセクションは変更しなければなりません。

GitHub App:

env:
  GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
  PR_ID: ${{ github.event.pull_request.node_id }}

Personal access token:

env:
  GITHUB_TOKEN: ${{ secrets.YOUR_TOKEN }}
  PR_ID: ${{ github.event.pull_request.node_id }}
このステップのための環境変数を設定します。 GITHUB_TOKENは上で説明されています。 PR_IDは、このワークフローをトリガーしたPull RequestのIDです。
item_id="$( gh api graphql -f query='
  mutation($project:ID!, $pr:ID!) {
    addProjectNextItem(input: {projectId: $project, contentId: $pr}) {
      projectNextItem {
        id
      }
    }
  }' -f project=$PROJECT_ID -f pr=$PR_ID --jq '.data.addProjectNextItem.projectNextItem.id')"
GitHub CLIとAPIを使って、このワークフローをトリガーしたPull Requestをプロジェクトに追加します。 jqフラグは、レスポンスをパースして作成されたアイテムのIDを取得します。
echo 'ITEM_ID='$item_id >> $GITHUB_ENV
作成されたアイテムのIDを環境変数として保存します。
echo "DATE=$(date +"%Y-%m-%d")" >> $GITHUB_ENV
現在の日付をyyyy-mm-ddというフォーマットで環境変数に保存します。

GitHub App:

env:
  GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}

Personal access token:

env:
  GITHUB_TOKEN: ${{ secrets.YOUR_TOKEN }}
このステップのための環境変数を設定します。 GITHUB_TOKENは上で説明されています。
gh api graphql -f query='
  mutation (
    $project: ID!
    $item: ID!
    $status_field: ID!
    $status_value: String!
    $date_field: ID!
    $date_value: String!
  ) {
    set_status: updateProjectNextItemField(input: {
      projectId: $project
      itemId: $item
      fieldId: $status_field
      value: $status_value
    }) {
      projectNextItem {
        id
        }
    }
    set_date_posted: updateProjectNextItemField(input: {
      projectId: $project
      itemId: $item
      fieldId: $date_field
      value: $date_value
    }) {
      projectNextItem {
        id
      }
    }
  }' -f project=$PROJECT_ID -f item=$ITEM_ID -f status_field=$STATUS_FIELD_ID -f status_value=${{ env.TODO_OPTION_ID }} -f date_field=$DATE_FIELD_ID -f date_value=$DATE --silent
Statusフィールドの値をTodoに設定します。 Date postedフィールドの値を設定します。