跳至主要内容

使用 Actions 自动化项目

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

GitHub Actions 工作流程

本文演示如何使用 GraphQL API 和 GitHub Actions 将 Pull Request 添加到组织项目。在工作流程示例中,当 Pull Request 被标记为“已准备好审查”时,将在项目中添加一个新的任务,其“状态”字段设置为“待办”,并将当前日期添加到自定义“发布日期”字段。

您可以复制下面的一个工作流程,并根据下表中的说明进行修改,以满足您的需求。

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

本文档假设您已经了解 GitHub Actions 的基础知识。有关 GitHub Actions 的更多信息,请参阅“GitHub Actions 文档”。

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

您可能还想使用由 GitHub 维护的 **actions/add-to-project** 工作流程,它会将当前问题或拉取请求添加到指定的项目中。有关更多信息,请参阅 actions/add-to-project 代码库和自述文件。

注意

GITHUB_TOKEN 的作用域限定为仓库级别,无法访问项目。要访问项目,您可以创建 GitHub 应用(推荐用于组织项目)或个人访问令牌(推荐用于用户项目)。下面显示了两种方法的工作流程示例。

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

有关使用 GitHub 应用在 GitHub Actions 工作流程中进行身份验证的更多信息,请参阅“在 GitHub Actions 工作流程中使用 GitHub 应用进行身份验证的 API 请求”。

  1. 创建一个 GitHub 应用或选择您组织拥有的现有 GitHub 应用。有关更多信息,请参阅“注册 GitHub 应用”。

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

    注意

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

  3. 在您的组织中安装 GitHub 应用。为您的项目需要访问的所有仓库安装它。有关更多信息,请参阅“安装您自己的 GitHub 应用”。

  4. 将您的 GitHub 应用 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。为了使此特定示例能够正常工作,您的项目还必须具有“发布日期”日期字段。

YAML
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: actions/create-github-app-token@v1
        with:
          app-id: ${{ vars.APP_ID }}
          private-key: ${{ secrets.APP_PEM }}

使用 actions/create-github-app-token 操作根据应用 ID 和私钥为您的应用生成安装访问令牌。安装访问令牌稍后在工作流程中作为 ${{ steps.generate-token.outputs.token }} 访问。

APP_ID 替换为包含应用 ID 的配置变量的名称。

APP_PEM 替换为包含应用私钥的密钥的名称。

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

为此步骤设置环境变量。

YOUR_ORGANIZATION 替换为您的组织名称。例如,octo-org

YOUR_PROJECT_NUMBER 替换为您的项目编号。要查找项目编号,请查看项目 URL。例如,https://github.com/orgs/octo-org/projects/5 的项目编号为 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

使用 GitHub CLI 查询项目的 API 以获取项目的 ID,并返回项目中前 20 个字段的名称和 ID。fields 返回一个联合体,查询使用内联片段(... on)返回有关任何 ProjectV2FieldProjectV2SingleSelectField 字段的信息。响应存储在一个名为 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

解析 API 查询的响应并将相关 ID 存储为环境变量。修改此内容以获取不同字段或选项的 ID。例如

  • 要获取名为 Team 的字段的 ID,请添加 echo 'TEAM_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") | .id' project_data.json) >> $GITHUB_ENV
  • 要获取 Team 单选字段中名为 Octoteam 的选项的 ID,请添加 echo 'OCTOTEAM_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") |.options[] | select(.name=="Octoteam") |.id' project_data.json) >> $GITHUB_ENV

注意:此工作流程假设您有一个名为“状态”的单选字段和一个名为“发布日期”的日期字段的项目,其中包含名为“待办”的选项。您必须修改此部分以匹配表中存在的字段。

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

为此步骤设置环境变量。GH_TOKEN 是第一步中生成的令牌。PR_ID 是触发此工作流程的拉取请求的 ID。

        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')"

使用 GitHub CLI 和 API 将触发此工作流程的拉取请求添加到项目中。jq 标志解析响应以获取已创建项目的 ID。

          echo 'ITEM_ID='$item_id >> $GITHUB_ENV

将已创建项目的 ID 存储为环境变量。

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

yyyy-mm-dd 格式将当前日期保存为环境变量。

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

为此步骤设置环境变量。GH_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

Status 字段的值设置为 Todo。设置 Date posted 字段的值。

#
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 [actions/create-github-app-token](https://github.com/marketplace/actions/create-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: actions/create-github-app-token@v1
        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

使用个人访问令牌进行身份验证的工作流程示例

  1. 创建一个具有 projectrepo 作用域的个人访问令牌(经典版)。有关更多信息,请参阅“管理您的个人访问令牌”。
  2. 将个人访问令牌保存为仓库或组织中的密钥。
  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:

每当仓库中的拉取请求被标记为“已准备好审查”时,此工作流程就会运行。

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

为此步骤设置环境变量。

如果您使用的是个人访问令牌,请将 YOUR_TOKEN 替换为包含个人访问令牌的密钥的名称。

YOUR_ORGANIZATION 替换为您的组织名称。例如,octo-org

YOUR_PROJECT_NUMBER 替换为您的项目编号。要查找项目编号,请查看项目 URL。例如,https://github.com/orgs/octo-org/projects/5 的项目编号为 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

使用 GitHub CLI 查询项目的 API 以获取项目的 ID,并返回项目中前 20 个字段的名称和 ID。fields 返回一个联合体,查询使用内联片段(... on)返回有关任何 ProjectV2FieldProjectV2SingleSelectField 字段的信息。响应存储在一个名为 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

解析 API 查询的响应并将相关 ID 存储为环境变量。修改此内容以获取不同字段或选项的 ID。例如

  • 要获取名为 Team 的字段的 ID,请添加 echo 'TEAM_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") | .id' project_data.json) >> $GITHUB_ENV
  • 要获取 Team 单选字段中名为 Octoteam 的选项的 ID,请添加 echo 'OCTOTEAM_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") |.options[] | select(.name=="Octoteam") |.id' project_data.json) >> $GITHUB_ENV

注意:此工作流程假设您有一个名为“状态”的单选字段和一个名为“发布日期”的日期字段的项目,其中包含名为“待办”的选项。您必须修改此部分以匹配表中存在的字段。

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

为此步骤设置环境变量。将 YOUR_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')"

使用 GitHub CLI 和 API 将触发此工作流程的拉取请求添加到项目中。jq 标志解析响应以获取已创建项目的 ID。

          echo 'ITEM_ID='$item_id >> $GITHUB_ENV

将已创建项目的 ID 存储为环境变量。

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

yyyy-mm-dd 格式将当前日期保存为环境变量。

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

为此步骤设置环境变量。将 YOUR_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

Status 字段的值设置为 Todo。设置 Date posted 字段的值。

# 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