Skip to main content

使用 Actions 自动化 Projects

可以使用 GitHub Actions 自动化你的项目。

GitHub Actions 工作流程

本文说明如何使用 GraphQL API 和 GitHub Actions 向组织项目添加拉取请求。 在示例工作流程中,当拉取请求标记为“准备审核”时,项目中会添加一项“状态”字段设置为“待办”的新任务,并且当前日期添加到自定义的“发布日期”字段中。

您可以复制以下工作流程之一,并按照下表中的说明对其进行修改,以满足您的需求。

项目可以跨越多个仓库,但工作流是特定于仓库的。 将工作流添加到希望项目跟踪的每个存储库。有关创建工作流文件的详细信息,请参阅“GitHub Actions 快速入门”。

本文假设您基本了解 GitHub Actions。 有关 GitHub Actions 的详细信息,请参阅“GitHub Actions 文档”。

有关可以通过 API 对项目进行的其他更改的详细信息,请参阅“使用 API 管理 Projects”。

你可能还希望使用 actions/add-to-project 工作流,该工作流由 GitHub 维护,并将当前问题或拉取请求添加到指定的项目。 有关详细信息,请参阅 actions/add-to-project 存储库和自述文件。

Note

GITHUB_TOKEN 的范围限定为存储库级别,并且无法访问 projects。 若要访问 projects,可以创建 GitHub App(建议用于组织项目)或者 personal access token(建议用于用户项目)。 下面显示了这两种方法的工作流程示例。

使用 GitHub App 进行身份验证的示例工作流程

有关使用 GitHub App 在 GitHub Actions 工作流中进行身份验证的详细信息,请参阅“使用 GitHub Actions 工作流中的 GitHub App 发出经过身份验证的 API 请求”。

  1. 创建 GitHub App 或选择组织拥有的现有 GitHub App。 有关详细信息,请参阅“注册 GitHub 应用”。

  2. 授予 GitHub App 对组织项目的读取和写入权限。 对于此特定示例,你的 GitHub App 还需要有对存储库拉取请求和存储库问题的读取权限。 有关详细信息,请参阅“修改 GitHub 应用注册”。

    Note

    你可以控制应用对组织项目和存储库项目的权限。 您必须授予读取和写入组织项目的权限;读取和写入存储库项目的权限是不够的。

  3. 在组织中安装 GitHub App。 为项目需要访问的所有存储库安装它。 有关详细信息,请参阅“安装自己的 GitHub 应用”。

  4. 将 GitHub App 的 ID 作为配置变量存储在存储库或组织中。 在下面的工作流中,将 APP_ID 替换为配置变量的名称。 您可以在应用的设置页面上或通过应用 API 找到应用 ID。 有关详细信息,请参阅“应用的 REST API 终结点”。 有关配置变量的详细信息,请参阅“在变量中存储信息”。

  5. 为应用生成私钥。 将生成的文件的内容作为机密存储在存储库或组织中。 (存储文件的全部内容,包括 -----BEGIN RSA PRIVATE KEY----------END RSA PRIVATE KEY-----。)在以下工作流中,将 APP_PEM 替换为机密的名称。 有关详细信息,请参阅“管理 GitHub 应用的私钥”。 有关存储机密的详细信息,请参阅“在 GitHub Actions 中使用机密”。

  6. 在以下工作流中,将 YOUR_ORGANIZATION 替换为组织的名称。 例如 octo-org。 将 YOUR_PROJECT_NUMBER 替换为项目编号。 要查找项目编号,请查看项目 URL。 例如,https://github.com/orgs/octo-org/projects/5 的项目编号为 5。 为了使此特定示例正常运行,项目还必须具有一个“发布日期”的日期字段。

    Note

    • 此工作流使用未通过 GitHub 认证的操作。 这些操作由第三方提供,并受单独的服务条款、隐私政策和支持文档的管辖。
    • GitHub 建议将操作固定到提交 SHA。 若要获取较新版本,需要更新 SHA。 还可以引用标记或分支,但该操作可能会更改而不发出警告。
YAML
name: Add PR to project
on:
  pull_request:
    types:
      - ready_for_review
jobs:
  track_pr:
    runs-on: ubuntu-latest
    steps:

This workflow runs whenever a pull request in the repository is marked as "ready for review".

      - name: Generate token
        id: generate-token
        uses: tibdex/github-app-token@32691ba7c9e7063bd457bd8f2a5703138591fa58 # v1.9.0
        with:
          app_id: ${{ vars.APP_ID }}
          private_key: ${{ secrets.APP_PEM }}

Uses the tibdex/github-app-token action to generate an installation access token for your app from the app ID and private key. The installation access token is accessed later in the workflow as ${{ steps.generate-token.outputs.token }}.

Replace APP_ID with the name of the configuration variable that contains your app ID.

Replace APP_PEM with the name of the secret that contains your app private key.

      - name: Get project data
        env:
          GH_TOKEN: ${{ steps.generate-token.outputs.token }}
          ORGANIZATION: YOUR_ORGANIZATION
          PROJECT_NUMBER: YOUR_PROJECT_NUMBER

Sets environment variables for this step.

Replace YOUR_ORGANIZATION with the name of your organization. For example, octo-org.

Replace YOUR_PROJECT_NUMBER with your project number. To find the project number, look at the project URL. For example, https://github.com/orgs/octo-org/projects/5 has a project number of 5.

        run: |
          gh api graphql -f query='
            query($org: String!, $number: Int!) {
              organization(login: $org){
                projectV2(number: $number) {
                  id
                  fields(first:20) {
                    nodes {
                      ... on ProjectV2Field {
                        id
                        name
                      }
                      ... on ProjectV2SingleSelectField {
                        id
                        name
                        options {
                          id
                          name
                        }
                      }
                    }
                  }
                }
              }
            }' -f org=$ORGANIZATION -F number=$PROJECT_NUMBER > project_data.json

Uses GitHub CLI to query the API for the ID of the project and return the name and ID of the first 20 fields in the project. fields returns a union and the query uses inline fragments (... on) to return information about any ProjectV2Field and ProjectV2SingleSelectField fields. The response is stored in a file called project_data.json.

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

Parses the response from the API query and stores the relevant IDs as environment variables. Modify this to get the ID for different fields or options. For example:

  • To get the ID of a field called Team, add echo 'TEAM_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") | .id' project_data.json) >> $GITHUB_ENV.
  • To get the ID of an option called Octoteam for the Team single select field, add echo 'OCTOTEAM_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") |.options[] | select(.name=="Octoteam") |.id' project_data.json) >> $GITHUB_ENV.

Note: This workflow assumes that you have a project with a single select field called "Status" that includes an option called "Todo" and a date field called "Date posted". You must modify this section to match the fields that are present in your table.

      - name: Add PR to project
        env:
          GH_TOKEN: ${{ steps.generate-token.outputs.token }}
          PR_ID: ${{ github.event.pull_request.node_id }}

Sets environment variables for this step. GH_TOKEN is the token generated in the first step. PR_ID is the ID of the pull request that triggered this workflow.

        run: |
          item_id="$( gh api graphql -f query='
            mutation($project:ID!, $pr:ID!) {
              addProjectV2ItemById(input: {projectId: $project, contentId: $pr}) {
                item {
                  id
                }
              }
            }' -f project=$PROJECT_ID -f pr=$PR_ID --jq '.data.addProjectV2ItemById.item.id')"

Uses GitHub CLI and the API to add the pull request that triggered this workflow to the project. The jq flag parses the response to get the ID of the created item.

          echo 'ITEM_ID='$item_id >> $GITHUB_ENV

Stores the ID of the created item as an environment variable.

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

Saves the current date as an environment variable in yyyy-mm-dd format.

      - name: Set fields
        env:
          GH_TOKEN: ${{ steps.generate-token.outputs.token }}

Sets environment variables for this step. GH_TOKEN is the token generated in the first step.

        run: |
          gh api graphql -f query='
            mutation (
              $project: ID!
              $item: ID!
              $status_field: ID!
              $status_value: String!
              $date_field: ID!
              $date_value: Date!
            ) {
              set_status: updateProjectV2ItemFieldValue(input: {
                projectId: $project
                itemId: $item
                fieldId: $status_field
                value: {
                  singleSelectOptionId: $status_value
                  }
              }) {
                projectV2Item {
                  id
                  }
              }
              set_date_posted: updateProjectV2ItemFieldValue(input: {
                projectId: $project
                itemId: $item
                fieldId: $date_field
                value: {
                  date: $date_value
                }
              }) {
                projectV2Item {
                  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

Sets the value of the Status field to Todo. Sets the value of the Date posted field.

#
name: Add PR to project
# This workflow runs whenever a pull request in the repository is marked as "ready for review".
on:
  pull_request:
    types:
      - ready_for_review
jobs:
  track_pr:
    runs-on: ubuntu-latest
    steps:
    # Uses the [tibdex/github-app-token](https://github.com/tibdex/github-app-token) action to generate an installation access token for your app from the app ID and private key. The installation access token is accessed later in the workflow as `${{ steps.generate-token.outputs.token }}`.
    #
    # Replace `APP_ID` with the name of the configuration variable that contains your app ID.
    #
    # Replace `APP_PEM` with the name of the secret that contains your app private key.
      - name: Generate token
        id: generate-token
        uses: tibdex/github-app-token@32691ba7c9e7063bd457bd8f2a5703138591fa58 # v1.9.0
        with:
          app_id: ${{ vars.APP_ID }}
          private_key: ${{ secrets.APP_PEM }}
      # Sets environment variables for this step.
      #
      # Replace `YOUR_ORGANIZATION` with the name of your organization. For example, `octo-org`.
      #
      # Replace `YOUR_PROJECT_NUMBER` with your project number. To find the project number, look at the project URL. For example, `https://github.com/orgs/octo-org/projects/5` has a project number of 5.
      - name: Get project data
        env:
          GH_TOKEN: ${{ steps.generate-token.outputs.token }}
          ORGANIZATION: YOUR_ORGANIZATION
          PROJECT_NUMBER: YOUR_PROJECT_NUMBER
        # Uses [GitHub CLI](https://cli.github.com/manual/) to query the API for the ID of the project and return the name and ID of the first 20 fields in the project. `fields` returns a union and the query uses inline fragments (`... on`) to return information about any `ProjectV2Field` and `ProjectV2SingleSelectField` fields. The response is stored in a file called `project_data.json`.
        run: |
          gh api graphql -f query='
            query($org: String!, $number: Int!) {
              organization(login: $org){
                projectV2(number: $number) {
                  id
                  fields(first:20) {
                    nodes {
                      ... on ProjectV2Field {
                        id
                        name
                      }
                      ... on ProjectV2SingleSelectField {
                        id
                        name
                        options {
                          id
                          name
                        }
                      }
                    }
                  }
                }
              }
            }' -f org=$ORGANIZATION -F number=$PROJECT_NUMBER > project_data.json

          # Parses the response from the API query and stores the relevant IDs as environment variables. Modify this to get the ID for different fields or options. For example:
          #
          # - To get the ID of a field called `Team`, add `echo 'TEAM_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") | .id' project_data.json) >> $GITHUB_ENV`.
          # - To get the ID of an option called `Octoteam` for the `Team` single select field, add `echo 'OCTOTEAM_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") |.options[] | select(.name=="Octoteam") |.id' project_data.json) >> $GITHUB_ENV`.
          #
          # **Note:** This workflow assumes that you have a project with a single select field called "Status" that includes an option called "Todo" and a date field called "Date posted". You must modify this section to match the fields that are present in your table.

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

# Sets environment variables for this step. `GH_TOKEN` is the token generated in the first step. `PR_ID` is the ID of the pull request that triggered this workflow.
      - name: Add PR to project
        env:
          GH_TOKEN: ${{ steps.generate-token.outputs.token }}
          PR_ID: ${{ github.event.pull_request.node_id }}
        # Uses [GitHub CLI](https://cli.github.com/manual/) and the API to add the pull request that triggered this workflow to the project. The `jq` flag parses the response to get the ID of the created item.
        run: |
          item_id="$( gh api graphql -f query='
            mutation($project:ID!, $pr:ID!) {
              addProjectV2ItemById(input: {projectId: $project, contentId: $pr}) {
                item {
                  id
                }
              }
            }' -f project=$PROJECT_ID -f pr=$PR_ID --jq '.data.addProjectV2ItemById.item.id')"

          # Stores the ID of the created item as an environment variable.
          echo 'ITEM_ID='$item_id >> $GITHUB_ENV

# Saves the current date as an environment variable in `yyyy-mm-dd` format.
      - name: Get date
        run: echo "DATE=$(date +"%Y-%m-%d")" >> $GITHUB_ENV

# Sets environment variables for this step. `GH_TOKEN` is the token generated in the first step.
      - name: Set fields
        env:
          GH_TOKEN: ${{ steps.generate-token.outputs.token }}
        # Sets the value of the `Status` field to `Todo`. Sets the value of the `Date posted` field.
        run: |
          gh api graphql -f query='
            mutation (
              $project: ID!
              $item: ID!
              $status_field: ID!
              $status_value: String!
              $date_field: ID!
              $date_value: Date!
            ) {
              set_status: updateProjectV2ItemFieldValue(input: {
                projectId: $project
                itemId: $item
                fieldId: $status_field
                value: {
                  singleSelectOptionId: $status_value
                  }
              }) {
                projectV2Item {
                  id
                  }
              }
              set_date_posted: updateProjectV2ItemFieldValue(input: {
                projectId: $project
                itemId: $item
                fieldId: $date_field
                value: {
                  date: $date_value
                }
              }) {
                projectV2Item {
                  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

使用 personal access token 进行身份验证的示例工作流程

  1. 使用 projectrepo 范围创建 personal access token (classic)。 有关详细信息,请参阅“管理个人访问令牌”。
  2. 将 personal access token 保存为存储库或组织中的机密。
  3. 在以下工作流中,将 YOUR_TOKEN 替换为机密的名称。 将 YOUR_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:

This workflow runs whenever a pull request in the repository is marked as "ready for review".

      - name: Get project data
        env:
          GH_TOKEN: ${{ secrets.YOUR_TOKEN }}
          ORGANIZATION: YOUR_ORGANIZATION
          PROJECT_NUMBER: YOUR_PROJECT_NUMBER

Sets environment variables for this step.

If you are using a personal access token, replace YOUR_TOKEN with the name of the secret that contains your personal access token.

Replace YOUR_ORGANIZATION with the name of your organization. For example, octo-org.

Replace YOUR_PROJECT_NUMBER with your project number. To find the project number, look at the project URL. For example, https://github.com/orgs/octo-org/projects/5 has a project number of 5.

        run: |
          gh api graphql -f query='
            query($org: String!, $number: Int!) {
              organization(login: $org){
                projectV2(number: $number) {
                  id
                  fields(first:20) {
                    nodes {
                      ... on ProjectV2Field {
                        id
                        name
                      }
                      ... on ProjectV2SingleSelectField {
                        id
                        name
                        options {
                          id
                          name
                        }
                      }
                    }
                  }
                }
              }
            }' -f org=$ORGANIZATION -F number=$PROJECT_NUMBER > project_data.json

Uses GitHub CLI to query the API for the ID of the project and return the name and ID of the first 20 fields in the project. fields returns a union and the query uses inline fragments (... on) to return information about any ProjectV2Field and ProjectV2SingleSelectField fields. The response is stored in a file called project_data.json.

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

Parses the response from the API query and stores the relevant IDs as environment variables. Modify this to get the ID for different fields or options. For example:

  • To get the ID of a field called Team, add echo 'TEAM_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") | .id' project_data.json) >> $GITHUB_ENV.
  • To get the ID of an option called Octoteam for the Team single select field, add echo 'OCTOTEAM_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") |.options[] | select(.name=="Octoteam") |.id' project_data.json) >> $GITHUB_ENV.

Note: This workflow assumes that you have a project with a single select field called "Status" that includes an option called "Todo" and a date field called "Date posted". You must modify this section to match the fields that are present in your table.

      - name: Add PR to project
        env:
          GH_TOKEN: ${{ secrets.YOUR_TOKEN }}
          PR_ID: ${{ github.event.pull_request.node_id }}

Sets environment variables for this step. Replace YOUR_TOKEN with the name of the secret that contains your personal access token.

        run: |
          item_id="$( gh api graphql -f query='
            mutation($project:ID!, $pr:ID!) {
              addProjectV2ItemById(input: {projectId: $project, contentId: $pr}) {
                item {
                  id
                }
              }
            }' -f project=$PROJECT_ID -f pr=$PR_ID --jq '.data.addProjectV2ItemById.item.id')"

Uses GitHub CLI and the API to add the pull request that triggered this workflow to the project. The jq flag parses the response to get the ID of the created item.

          echo 'ITEM_ID='$item_id >> $GITHUB_ENV

Stores the ID of the created item as an environment variable.

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

Saves the current date as an environment variable in yyyy-mm-dd format.

      - name: Set fields
        env:
          GH_TOKEN: ${{ secrets.YOUR_TOKEN }}

Sets environment variables for this step. Replace YOUR_TOKEN with the name of the secret that contains your personal access token.

        run: |
          gh api graphql -f query='
            mutation (
              $project: ID!
              $item: ID!
              $status_field: ID!
              $status_value: String!
              $date_field: ID!
              $date_value: Date!
            ) {
              set_status: updateProjectV2ItemFieldValue(input: {
                projectId: $project
                itemId: $item
                fieldId: $status_field
                value: {
                  singleSelectOptionId: $status_value
                  }
              }) {
                projectV2Item {
                  id
                  }
              }
              set_date_posted: updateProjectV2ItemFieldValue(input: {
                projectId: $project
                itemId: $item
                fieldId: $date_field
                value: {
                  date: $date_value
                }
              }) {
                projectV2Item {
                  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

Sets the value of the Status field to Todo. Sets the value of the Date posted field.

# This workflow runs whenever a pull request in the repository is marked as "ready for review".
name: Add PR to project
on:
  pull_request:
    types:
      - ready_for_review
jobs:
  track_pr:
    runs-on: ubuntu-latest
    steps:
    # Sets environment variables for this step.
    #
    # If you are using a personal access token, replace `YOUR_TOKEN` with the name of the secret that contains your personal access token.
    #
    # Replace `YOUR_ORGANIZATION` with the name of your organization. For example, `octo-org`.
    #
    # Replace `YOUR_PROJECT_NUMBER` with your project number. To find the project number, look at the project URL. For example, `https://github.com/orgs/octo-org/projects/5` has a project number of 5.
      - name: Get project data
        env:
          GH_TOKEN: ${{ secrets.YOUR_TOKEN }}
          ORGANIZATION: YOUR_ORGANIZATION
          PROJECT_NUMBER: YOUR_PROJECT_NUMBER
        # Uses [GitHub CLI](https://cli.github.com/manual/) to query the API for the ID of the project and return the name and ID of the first 20 fields in the project. `fields` returns a union and the query uses inline fragments (`... on`) to return information about any `ProjectV2Field` and `ProjectV2SingleSelectField` fields. The response is stored in a file called `project_data.json`.
        run: |
          gh api graphql -f query='
            query($org: String!, $number: Int!) {
              organization(login: $org){
                projectV2(number: $number) {
                  id
                  fields(first:20) {
                    nodes {
                      ... on ProjectV2Field {
                        id
                        name
                      }
                      ... on ProjectV2SingleSelectField {
                        id
                        name
                        options {
                          id
                          name
                        }
                      }
                    }
                  }
                }
              }
            }' -f org=$ORGANIZATION -F number=$PROJECT_NUMBER > project_data.json

          # Parses the response from the API query and stores the relevant IDs as environment variables. Modify this to get the ID for different fields or options. For example:
          #
          # - To get the ID of a field called `Team`, add `echo 'TEAM_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") | .id' project_data.json) >> $GITHUB_ENV`.
          # - To get the ID of an option called `Octoteam` for the `Team` single select field, add `echo 'OCTOTEAM_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") |.options[] | select(.name=="Octoteam") |.id' project_data.json) >> $GITHUB_ENV`.
          #
          # **Note:** This workflow assumes that you have a project with a single select field called "Status" that includes an option called "Todo" and a date field called "Date posted". You must modify this section to match the fields that are present in your table.
          
          echo 'PROJECT_ID='$(jq '.data.organization.projectV2.id' project_data.json) >> $GITHUB_ENV
          echo 'DATE_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Date posted") | .id' project_data.json) >> $GITHUB_ENV
          echo 'STATUS_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Status") | .id' project_data.json) >> $GITHUB_ENV
          echo 'TODO_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Status") | .options[] | select(.name=="Todo") |.id' project_data.json) >> $GITHUB_ENV

# Sets environment variables for this step. Replace `YOUR_TOKEN` with the name of the secret that contains your personal access token.
      - name: Add PR to project
        env:
          GH_TOKEN: ${{ secrets.YOUR_TOKEN }}
          PR_ID: ${{ github.event.pull_request.node_id }}
        # Uses [GitHub CLI](https://cli.github.com/manual/) and the API to add the pull request that triggered this workflow to the project. The `jq` flag parses the response to get the ID of the created item.
        run: |
          item_id="$( gh api graphql -f query='
            mutation($project:ID!, $pr:ID!) {
              addProjectV2ItemById(input: {projectId: $project, contentId: $pr}) {
                item {
                  id
                }
              }
            }' -f project=$PROJECT_ID -f pr=$PR_ID --jq '.data.addProjectV2ItemById.item.id')"

          # Stores the ID of the created item as an environment variable.
          echo 'ITEM_ID='$item_id >> $GITHUB_ENV

# Saves the current date as an environment variable in `yyyy-mm-dd` format.
      - name: Get date
        run: echo "DATE=$(date +"%Y-%m-%d")" >> $GITHUB_ENV

# Sets environment variables for this step. Replace `YOUR_TOKEN` with the name of the secret that contains your personal access token.
      - name: Set fields
        env:
          GH_TOKEN: ${{ secrets.YOUR_TOKEN }}
        # Sets the value of the `Status` field to `Todo`. Sets the value of the `Date posted` field.
        run: |
          gh api graphql -f query='
            mutation (
              $project: ID!
              $item: ID!
              $status_field: ID!
              $status_value: String!
              $date_field: ID!
              $date_value: Date!
            ) {
              set_status: updateProjectV2ItemFieldValue(input: {
                projectId: $project
                itemId: $item
                fieldId: $status_field
                value: {
                  singleSelectOptionId: $status_value
                  }
              }) {
                projectV2Item {
                  id
                  }
              }
              set_date_posted: updateProjectV2ItemFieldValue(input: {
                projectId: $project
                itemId: $item
                fieldId: $date_field
                value: {
                  date: $date_value
                }
              }) {
                projectV2Item {
                  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