Skip to main content
Мы публикуем частые обновления нашей документации, и перевод этой страницы, возможно, еще выполняется. Актуальные сведения см. в документации на английском языке.

Автоматизация Projects с помощью Actions

Для автоматизации проектов можно использовать GitHub Actions.

Рабочие процессы GitHub Actions

В этом разделе показано, как использовать API GraphQL и GitHub Actions для добавления запроса на вытягивание в проект организации. В примерах рабочих процессов, когда запрос на вытягивание помечен как "готов к проверке", в проект добавляется новая задача, для которой в поле "Состояние" указано "Выполнить", а в настраиваемое поле "Дата публикации" добавляется текущая дата.

Вы можете скопировать один из приведенных ниже рабочих процессов и изменить его, как описано в таблице ниже, в соответствии с вашими потребностями.

Проект может охватывать несколько репозиториев, но рабочий процесс зависит от репозитория. Добавьте рабочий процесс в каждый репозиторий, который будет отслеживать проект. Дополнительные сведения о создании файлов рабочего процесса см. в разделе Краткое руководство по GitHub Actions.

В этой статье предполагается, что у вас есть базовое представление о GitHub Actions. Дополнительные сведения о GitHub Actions см. в разделе Документация по GitHub Actions.

Дополнительные сведения о других изменениях, которые можно внести в проект с помощью API, см. в разделе Использование API для управления Projects.

Вы также можете использовать рабочий процесс actions/add-to-project, который поддерживается GitHub и добавит текущую проблему или запрос на вытягивание в указанный проект. Дополнительные сведения см. в репозитории actions/add-to-project и файле сведений.

Примечание. GITHUB_TOKEN ограничен уровнем репозитория и не может получить доступ к projects. Для доступа к projects можно создать GitHub App (рекомендуется для проектов организации) или personal access token (рекомендуется для пользовательских проектов). Ниже приведены примеры рабочих процессов для обоих подходов.

Пример проверки подлинности рабочего процесса при использовании GitHub App

  1. Создайте GitHub App или выберите существующий GitHub App, принадлежащий вашей организации. Дополнительные сведения см. в разделе Создание приложения GitHub.

  2. Предоставьте для GitHub App разрешения на чтение и запись в проектах организации. Дополнительные сведения см. в разделе Изменение разрешений приложения GitHub.

    Примечание. Вы можете управлять разрешением приложения в проектах организации и проектах репозитория. Необходимо предоставить разрешение на чтение и запись в проектах организации; разрешений на чтение и запись в проектах репозитория будет недостаточно.

  3. Установите GitHub App в вашей организации. Установите его для всех репозиториев, к которым проект должен получать доступ. Дополнительные сведения см. в разделе Установка приложений GitHub.

  4. Храните идентификатор GitHub App как секрет в репозитории или организации. В следующем рабочем процессе замените APP_ID именем секрета. Идентификатор приложения можно найти на странице параметров приложения или через API приложений. Дополнительные сведения см. в разделе Приложения.

  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.
# Они предоставляются сторонним поставщиком, и на них распространяются
# отдельные условия обслуживания, политика конфиденциальности и поддержка
# документации.

# GitHub рекомендует закрепить действия в фиксации SHA.
# Чтобы получить более новую версию, потребуется обновить SHA.
# Вы также можете ссылаться на тег или ветвь, однако действие может измениться без предупреждения.

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){
                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

          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

      - 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!) {
              addProjectV2ItemById(input: {projectId: $project, contentId: $pr}) {
                item {
                  id
                }
              }
            }' -f project=$PROJECT_ID -f pr=$PR_ID --jq '.data.addProjectV2ItemById.item.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: 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. Создайте personal access token (classic) с областями project и repo . Дополнительные сведения см. в разделе Создание личного маркера доступа.
  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:
      - 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){
                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

          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

      - 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!) {
              addProjectV2ItemById(input: {projectId: $project, contentId: $pr}) {
                item {
                  id
                }
              }
            }' -f project=$PROJECT_ID -f pr=$PR_ID --jq '.data.addProjectV2ItemById.item.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: 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

Описание рабочего процесса

В следующей таблице описаны разделы примеров рабочих процессов и показано, как адаптировать рабочие процессы для собственного использования.

on:
  pull_request:
    types:
      - ready_for_review
Этот рабочий процесс выполняется каждый раз, когда запрос на вытягивание в репозитории помечается как "готов к проверке".

Только GitHub App:

- 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 для создания маркера доступа установки для приложения на основе идентификатора приложения и закрытого ключа. Маркер доступа установки будет доступен позже в рабочем процессе как ${{ steps.generate_token.outputs.token }}.

Замените APP_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
Задает переменные среды для этого шага.

Если вы используете personal access token, замените YOUR_TOKEN именем секрета, содержащего personal access 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){
      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 идентификаторы, имена и параметры первых 20 полей в этом проекте. fields возвращает объединение, и в этом запросе используются встроенные фрагменты (... on) для передачи сведений о любых полях ProjectV2Field и ProjectV2SingleSelectField.

Ответ хранится в файле с именем 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 и сохраняет соответствующие идентификаторы в виде переменных среды. Измените его, чтобы получить идентификатор для различных полей или параметров. Пример:
  • Чтобы получить идентификатор поля с именем Team, добавьте echo 'TEAM_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") | .id' project_data.json) >> $GITHUB_ENV.
  • Чтобы получить идентификатор параметра с именем Octoteam для поля Team с одиночным выбором, добавьте echo 'OCTOTEAM_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") |.options[] | select(.name=="Octoteam") |.id' project_data.json) >> $GITHUB_ENV.
Примечание. В этом рабочем процессе предполагается, что у вас есть проект с полем одиночного выбора с именем "Состояние" и вариантом "Выполнить", а также поле даты с именем "Дата публикации". Этот раздел необходимо изменить в соответствии с полями, которые присутствуют в таблице.

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 — это идентификатор запроса на вытягивание, который активировал этот рабочий процесс.
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 анализирует ответ, чтобы получить идентификатор созданного элемента.
echo 'ITEM_ID='$item_id >> $GITHUB_ENV
Сохраняет идентификатор созданного элемента в качестве переменной среды.
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: 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.