Skip to main content

Automatizar Projects usando ações

Você pode usar o GitHub Actions para automatizar projetos.

Fluxos de trabalho GitHub Actions

Esta seção demonstra como usar a API do GraphQL e GitHub Actions para adicionar um pull request a um projeto da organização. No exemplo de fluxos de trabalho, quando o pull request é marcado como "pronto para revisão", uma nova tarefa é adicionada ao projeto com um campo "Status" definido como "Todo", e a data atual é adicionada a um campo personalizado "Data de postagem".

Você pode copiar um dos fluxos de trabalho abaixo e modificá-lo conforme descrito na tabela abaixo para atender às suas necessidades.

Um projeto pode incluir vários repositórios, mas um fluxo de trabalho é específico para um repositório. Adicione o fluxo de trabalho a cada repositório que deseja acompanhar no projeto. Para obter mais informações sobre como criar arquivos de fluxo de trabalho, confira "Guia de início rápido do GitHub Actions".

Este artigo pressupõe que você tem um entendimento básico de GitHub Actions. Para obter mais informações sobre o GitHub Actions, confira "GitHub Actions".

Para obter mais informações sobre outras alterações que você pode fazer no seu projeto por meio da API, confira "Como usar a API para gerenciar projetos".

Você também pode querer usar o fluxo de trabalho de ações/adicionar ao projeto, que é mantido pelo GitHub e adicionará o problema ou a solicitação de pull atual ao projeto especificado. Para obter mais informações, confira o repositório de ações/adicionar ao projeto e o LEIAME.

Observação: o GITHUB_TOKEN tem escopo para o nível do repositório e não pode acessar projects. Para acessar projects, você pode criar um GitHub App (recomendado para projetos de organização) ou um personal access token (recomendado para projetos de usuários). Exemplos de fluxo de trabalho para ambas as abordagens são mostrados abaixo.

Exemplo de fluxo de trabalho que efetua a autenticação com um GitHub App

  1. Crie um GitHub App ou escolha um GitHub App existente pertencente à sua organização. Para obter mais informações, confira "Como criar um GitHub App".

  2. Dê as suas permissões de leitura e gravação de GitHub App para projetos de organização. Para obter mais informações, confira "Como editar as permissões de um GitHub App".

    Observação: você pode controlar a permissão do aplicativo em projetos da organização e do repositório. Você deve dar permissão de leitura e gravação de projetos de organização; a permissão de leitura e gravação para projetos de repositório não será suficiente.

  3. Instale o GitHub App na sua organização. Instale-o em todos os repositórios que o seu projeto precisa acessar. Para obter mais informações, confira "Como instalar os GitHub Apps".

  4. Armazene o ID do seu GitHub App como um segredo no seu repositório ou organização. No fluxo de trabalho a seguir, substitua APP_ID pelo nome do segredo. Você pode encontrar o ID do seu aplicativo na página de configurações do seu aplicativo ou por meio da API do aplicativo. Para obter mais informações, confira "Aplicativos".

  5. Gerar uma chave privada para o seu aplicativo. Armazene o conteúdo do arquivo resultante como um segredo no seu repositório ou organização. (Armazene todo o conteúdo do arquivo, incluindo -----BEGIN RSA PRIVATE KEY----- e -----END RSA PRIVATE KEY-----). No fluxo de trabalho a seguir, substitua APP_PEM pelo nome do segredo. Para obter mais informações, confira "Autenticação com os GitHub Apps".

  6. No fluxo de trabalho a seguir, substitua YOUR_ORGANIZATION pelo nome da sua organização. Por exemplo, octo-org. Substitua YOUR_PROJECT_NUMBER pelo número do projeto. Para encontrar o número do projeto, consulte a URL do projeto. Por exemplo, https://github.com/orgs/octo-org/projects/5 tem o número de projeto 5.

YAML
# Esse fluxo de trabalho usa ações que não são certificadas pelo GitHub.
# São fornecidas por terceiros e regidas por
# termos de serviço, política de privacidade e suporte separados
# online.

# O GitHub recomenda fixar ações em um SHA de commit.
# Para obter uma versão mais recente, você precisará atualizar o SHA.
# Você também pode fazer referência a uma marca ou branch, mas a ação pode ser alterada sem aviso.

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

Exemplo de fluxo de trabalho que faz a autenticação com um personal access token

  1. Crie um personal access token (classic) com os escopos project e repo. Para obter mais informações, confira "Como criar um personal access token".
  2. Salve o personal access token como um segredo no repositório ou na organização.
  3. No fluxo de trabalho a seguir, substitua YOUR_TOKEN pelo nome do segredo. Substitua YOUR_ORGANIZATION pelo nome da sua organização. Por exemplo, octo-org. Substitua YOUR_PROJECT_NUMBER pelo número do projeto. Para encontrar o número do projeto, consulte a URL do projeto. Por exemplo, https://github.com/orgs/octo-org/projects/5 tem o número de projeto 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

Explicação do fluxo de trabalho

A tabela a seguir explica as seções dos fluxos de trabalho de exemplo e mostra como adaptar os fluxos de trabalho para seu próprio uso.

on:
  pull_request:
    types:
      - ready_for_review
Este fluxo de trabalho é executado sempre que um pull request no repositório for marcado como "pronto para revisão".

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 }}
Usa a ação tibdex/github-app-token para gerar um token de acesso de instalação para seu aplicativo por meio da ID do aplicativo e da chave privada. O token de acesso à instalação é acessado posteriormente no fluxo de trabalho como ${{ steps.generate_token.outputs.token }}.

Substitua APP_ID pelo nome do segredo que contém a ID do aplicativo.

Substitua APP_PEM pelo nome do segredo que contém a chave privada do aplicativo.

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
Define variáveis de ambiente para esta etapa.

Se você estiver usando um personal access token, substitua YOUR_TOKEN pelo nome do segredo que contém os dados de personal access token.

Substitua YOUR_ORGANIZATION pelo nome da sua organização. Por exemplo, octo-org.

Substitua YOUR_PROJECT_NUMBER pelo número do projeto. Para encontrar o número do projeto, consulte a URL do projeto. Por exemplo, https://github.com/orgs/octo-org/projects/5 tem o número de projeto 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

Usa a GitHub CLI para consultar a API da ID do projeto e a ID e retornar o nome e a ID dos primeiros 20 campos do projeto. fields retorna uma união e a consulta usa fragmentos embutidos (... on) para retornar informações sobre campos ProjectV2Field e ProjectV2SingleSelectField.

A resposta é armazenada em um arquivo chamado 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
Analisa a resposta da consulta da API e armazena os IDs relevantes como variáveis de ambiente. Modifique este ID para obter o ID para diferentes campos ou opções. Por exemplo:
  • Para obter a ID de um campo chamado Team, adicione echo 'TEAM_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") | .id' project_data.json) >> $GITHUB_ENV.
  • Para obter a ID de uma opção chamada Octoteam para o campo Team único selecionado, adicione echo 'OCTOTEAM_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") |.options[] | select(.name=="Octoteam") |.id' project_data.json) >> $GITHUB_ENV
Observação: esse fluxo de trabalho pressupõe que você tenha um projeto com um só campo de seleção chamado "Status" que inclui uma opção chamada "Tarefas pendentes" e um campo de data chamado "Data da postagem". Você deve modificar esta seção para corresponder aos campos presentes na sua tabela.

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 }}
Define variáveis de ambiente para esta etapa. O GITHUB_TOKEN é descrito acima. PR_ID é a ID da solicitação de pull que disparou esse fluxo de trabalho.
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')"
Usa a GitHub CLI e a API para adicionar a solicitação de pull que disparou esse fluxo de trabalho ao projeto. O sinalizador jq analisa a resposta para obter a ID do item criado.
echo 'ITEM_ID='$item_id >> $GITHUB_ENV
Armazena o ID do item criado como uma variável de ambiente.
echo "DATE=$(date +"%Y-%m-%d")" >> $GITHUB_ENV
Salva a data atual como uma variável de ambiente no formato yyyy-mm-dd.

GitHub App:

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

Personal access token:

env:
  GITHUB_TOKEN: ${{ secrets.YOUR_TOKEN }}
Define variáveis de ambiente para esta etapa. O GITHUB_TOKEN é descrito acima.
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
Define o valor do campo Status como Todo. Define o valor do campo Date posted.