Skip to main content

自动化项目(测试版)

您可以使用内置工作流程或 API 和 GitHub Actions 来管理项目。

注意: 项目(测试版)目前处于公开测试阶段,可能会有所变化。

简介

您可以添加自动化来帮助管理项目。 项目(测试版)包括可通过 UI 配置的内置工作流程。 此外,您可以使用 GraphQL API 和 GitHub Actions 编写自定义工作流程。

内置工作流程

项目(测试版)包括内置工作流程,可用于根据某些事件更新项的状态。 例如,您可以在项添加到项目时自动将状态设置为待办事项 ,或在议题关闭时将状态设置为完成

当项目初始化时,默认情况下会启用两个工作流程:当项目中的议题或拉取请求关闭时,其状态设置为完成;项目中的拉取请求合并时,其状态设置为完成

您可以为项目启用或禁用内置工作流程。

  1. 导航到您的项目。
  2. 在右上角,单击 以打开菜单。
  3. 在菜单中,单击 Workflows(工作流程)
  4. Default workflows(默认工作流程)下,单击要编辑的工作流程。
  5. 如果工作流程可以同时应用于议题和拉取请求,请在 When(何时)旁边,选中要对其执行操作的项类型。
  6. Set(设置)旁边,选择要将状态设置为的值。
  7. 如果工作流程已禁用,请单击 Disabled(已禁用)旁边的切换开关以启用工作流程。

GitHub Actions 工作流程

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

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

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

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

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

注意: GITHUB_TOKEN 的范围限定为存储库级别,无法访问项目(测试版)。 要访问项目(测试版),可以创建 GitHub 应用程序 (建议用于组织项目)或个人访问令牌(建议用于用户项目)。 下面显示了这两种方法的工作流程示例。

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

  1. 创建 GitHub 应用程序 或选择组织拥有的现有 GitHub 应用程序。 更多信息请参阅“创建 GitHub 应用程序”。

  2. 授予 GitHub 应用程序 对组织项目的读取和写入权限。 更多信息请参阅“编辑 GitHub 应用程序 的权限”。

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

  3. 在组织中安装 GitHub 应用程序。 为项目需要访问的所有存储库安装它。 更多信息请参阅“安装 GitHub 应用程序。”

  4. 将 GitHub 应用程序 的 ID 作为机密存储在存储库或组织中。 在以下工作流程中,将 APP_ID 替换为密钥的名称。 您可以在应用的设置页面上或通过应用 API 找到应用 ID。 更多信息请参阅“应用程序”。

  5. 为应用生成私钥。 将生成的文件的内容作为机密存储在存储库或组织中。 (存储文件的全部内容,包括 -----BEGIN RSA PRIVATE KEY----------END RSA PRIVATE KEY-----)。 在以下工作流程中,将 APP_PEM 替换为密钥的名称。 更多信息请参阅“向 GitHub 应用程序 验证”。

  6. 在以下工作流程中,将 YOUR_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. 将个人访问令牌另存为存储库或组织中的机密。
  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:
          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
当仓库中的拉取请求标记为“准备审核”时,此工作流程将运行。

GitHub 应用程序 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 和私钥为应用生成安装访问令牌。 稍后在工作流程中以s ${{ steps.generate_token.outputs.token }} 的形式访问安装访问令牌。

APP_ID 替换为包含应用 ID 的密钥的名称。

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

GitHub 应用程序:

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 替换为组织名称。 例如 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 的 API 以及项目前 20 个字段的 ID、名称和设置。 响应存储在一个名为 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. rbodiation.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
注意:此工作流假定您有一个名为“状态”的单选字段,其中包括一个名为“待办”的选项和一个名为“发布日期”的日期字段。 您必须修改此部分以匹配表中存在的字段。

GitHub 应用程序:

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 是触发此工作流程的拉取请求的 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 将触发此工作流程的拉取请求添加到项目。 jq 标志解析了获取已创建项的 ID 的响应。
echo 'ITEM_ID='$item_id >> $GITHUB_ENV
将已创建项的 ID 存储为环境变量。
echo "DATE=$(date +"%Y-%m-%d")" >> $GITHUB_ENV
yyy-mm-dd 格式保存当前日期为环境变量。

GitHub 应用程序:

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 字段的值。