Skip to main content

Automatisation des Projects avec Actions

Vous pouvez utiliser GitHub Actions pour automatiser vos projets.

Workflows GitHub Actions

Cette section montre comment utiliser l’API GraphQL et GitHub Actions pour ajouter une demande de tirage à un projet d’organisation. Dans l’exemple de workflows, lorsque la demande de tirage est marquée comme « prête pour évaluation », une nouvelle tâche est ajoutée au projet avec un champ « État » défini sur « À faire » et la date actuelle est ajoutée à un champ « Date publié » personnalisé.

Vous pouvez copier l’un des workflows ci-dessous et le modifier comme décrit dans le tableau ci-dessous pour répondre à vos besoins.

Un projet peut s’étendre sur plusieurs référentiels, mais un workflow est spécifique à un référentiel. Ajoutez le workflow à chaque référentiel que votre projet doit suivre. Pour plus d’informations sur la création de fichiers de workflow, consultez « Démarrage rapide pour GitHub Actions ».

Cet article part du principe que vous avez une compréhension de base de GitHub Actions. Pour plus d’informations sur GitHub Actions, consultez « GitHub Actions. »

Pour plus d’informations sur les autres modifications que vous pouvez apporter à votre projet via l’API, consultez « Utilisation de l’API pour gérer des projets ».

Vous pouvez aussi vouloir utiliser le workflow actions/add-to-project, qui est géré par GitHub et qui ajoute le problème ou la demande de tirage en cours dans le projet spécifié. Pour plus d’informations, consultez le dépôt actions/add-to-project et le fichier README.

Remarque : GITHUB_TOKEN est délimité au niveau du dépôt et ne peut pas accéder aux projects. Pour accéder aux projects, vous pouvez créer une GitHub App (recommandé pour les projets d’organisation) ou un personal access token (recommandé pour les projets d’utilisateur). Les exemples de workflow pour les deux approches sont présentés ci-dessous.

Exemple de workflow s’authentifiant avec un GitHub App

  1. Créez un GitHub App ou choisissez un GitHub App existant appartenant à votre organisation. Pour plus d’informations, consultez « Création d’un GitHub App ».

  2. Accordez à GitHub App des autorisations de lecture et d’écriture pour les projets de l’organisation. Pour plus d’informations, consultez « Modification des autorisations de GitHub App ».

    Remarque : vous pouvez contrôler l’autorisation de votre application pour les projets d’organisation et pour les projets de référentiel. Vous devez accorder l’autorisation de lecture et d’écriture des projets d’organisation ; l’autorisation de lecture et d’écriture des projets de référentiel ne suffit pas.

  3. Installation le GitHub App dans votre organisation. Installez-le pour tous les référentiels auxquels votre projet doit accéder. Pour plus d’informations, consultez « Installation de GitHub Apps ».

  4. Stockez votre id de GitHub App en tant que secret dans votre référentiel ou organisation. Dans le workflow suivant, remplacez APP_ID par le nom du secret. Vous pouvez trouver votre ID d’application dans la page Paramètres de votre application ou via l’API d’application. Pour plus d’informations, consultez « Applications. »

  5. Générez une clé privée pour votre application. Stockez le contenu du fichier résultant sous la forme d’un secret dans votre référentiel ou organisation. (Stockez l’intégralité du contenu du fichier, y compris -----BEGIN RSA PRIVATE KEY----- et -----END RSA PRIVATE KEY-----.) Dans le workflow suivant, remplacez APP_PEM par le nom du secret. Pour plus d’informations, consultez « Authentification avec des GitHub Apps ».

  6. Dans le workflow suivant, remplacez YOUR_ORGANIZATION par le nom de votre organisation. Par exemple : octo-org. Remplacez YOUR_PROJECT_NUMBER par votre numéro de projet. Pour trouver le numéro de projet, consultez l’URL du projet. Par exemple, https://github.com/orgs/octo-org/projects/5 a pour numéro de projet 5.

YAML
# <a name="this-workflow-uses-actions-that-are-not-certified-by-github"></a>Ce workflow utilise des actions qui ne sont pas certifiées par GitHub.
# <a name="they-are-provided-by-a-third-party-and-are-governed-by"></a>Elles sont fournies par un tiers et régies par
# <a name="separate-terms-of-service-privacy-policy-and-support"></a>des conditions d’utilisation du service, une politique de confidentialité et un support distincts.
# <a name="documentation"></a>documentation en ligne.

# <a name="github-recommends-pinning-actions-to-a-commit-sha"></a>GitHub recommande d’épingler les actions à un SHA de commit.
# <a name="to-get-a-newer-version-you-will-need-to-update-the-sha"></a>Pour obtenir une version plus récente, vous devez mettre à jour le SHA.
# <a name="you-can-also-reference-a-tag-or-branch-but-the-action-may-change-without-warning"></a>Vous pouvez également référencer une balise ou une branche, mais l’action peut changer sans avertissement.

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

Exemple de workflow s’authentifiant avec un personal access token

  1. Créez un personal access token (classic) avec les étendues project et repo. Pour plus d’informations, consultez « Création d’un personal access token ».
  2. Enregistrez le personal access token en tant que secret dans votre dépôt ou votre organisation.
  3. Dans le workflow suivant, remplacez YOUR_TOKEN par le nom du secret. Remplacez YOUR_ORGANIZATION par le nom de votre organisation. Par exemple : octo-org. Remplacez YOUR_PROJECT_NUMBER par votre numéro de projet. Pour trouver le numéro de projet, consultez l’URL du projet. Par exemple, https://github.com/orgs/octo-org/projects/5 a un nombre de projet de 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

Explication du workflow

Le tableau suivant décrit les sections de l’exemple de workflow et vous montre comment adapter les workflows à votre propre utilisation.

on:
  pull_request:
    types:
      - ready_for_review
Ce workflow s’exécute chaque fois qu’une demande de tirage dans le référentiel est marquée comme « prête pour évaluation ».

GitHub App seulement :

- name: Generate token
  id: generate_token
  uses: tibdex/github-app-token@36464acb844fc53b9b8b2401da68844f6b05ebb0
  with:
    app_id: ${{ secrets.APP_ID }}
    private_key: ${{ secrets.APP_PEM }}
Utilise l’action tibdex/github-app-token pour générer un jeton d’accès d’installation pour votre application à partir de l’ID d’application et de la clé privée. Le jeton d’accès à l’installation est accessible ultérieurement dans le workflow en tant que ${{ steps.generate_token.outputs.token }}.

Remplacez APP_ID par le nom du secret qui contient votre ID d’application.

Remplacez APP_PEM par le nom du secret qui contient la clé privée de votre application.

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
Définissez les variables d'environnement pour cette étape.

Si vous utilisez un personal access token, remplacez YOUR_TOKEN par le nom du secret qui contient votre personal access token.

Remplacez YOUR_ORGANIZATION par le nom de votre organisation. Par exemple : octo-org.

Remplacez YOUR_PROJECT_NUMBER par votre numéro de projet. Pour trouver le numéro de projet, consultez l’URL du projet. Par exemple, https://github.com/orgs/octo-org/projects/5 a pour numéro de projet 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

Utilise GitHub CLI pour interroger l’API pour l’ID du projet et retourne le nom et l’ID des 20 premiers champs du projet. fieldsretourne une union et la requête utilise des fragments inlined (... on) pour renvoyer des informations sur tous les champs ProjectV2Field et ProjectV2SingleSelectField.

La réponse est stockée dans un fichier appelé 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
Analyse la réponse de la requête d’API et stocke les ID pertinents en tant que variables d’environnement. Modifiez-le pour obtenir l’ID de différents champs ou options. Par exemple :
  • Pour obtenir l’ID d’un champ appelé Team, ajoutez echo 'TEAM_FIELD_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") | .id' project_data.json) >> $GITHUB_ENV.
  • Pour obtenir l’ID d’une option appelée Octoteam pour le seul champ sélectionné Team, ajoutez echo 'OCTOTEAM_OPTION_ID='$(jq '.data.organization.projectV2.fields.nodes[] | select(.name== "Team") |.options[] | select(.name=="Octoteam") |.id' project_data.json) >> $GITHUB_ENV
Remarque : Ce workflow suppose que vous disposez d’un projet avec un seul champ de sélection appelé « État » qui inclut une option appelée « À faire » et un champ de date appelé « Date publiée ». Vous devez modifier cette section pour qu’elle corresponde aux champs présents dans votre table.

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 }}
Définissez les variables d'environnement pour cette étape. GITHUB_TOKEN est décrit ci-dessus. PR_ID est l’ID de la demande de tirage qui a déclenché ce workflow.
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')"
Utilise GitHub CLI et l’API pour ajouter la demande de tirage qui a déclenché ce workflow dans le projet. L’indicateur jq analyse la réponse pour obtenir l’ID de l’élément créé.
echo 'ITEM_ID='$item_id >> $GITHUB_ENV
Stocke l’ID de l’élément créé en tant que variable d’environnement.
echo "DATE=$(date +"%Y-%m-%d")" >> $GITHUB_ENV
Enregistre la date actuelle en tant que variable d’environnement au format yyyy-mm-dd.

GitHub App:

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

Personal access token :

env:
  GITHUB_TOKEN: ${{ secrets.YOUR_TOKEN }}
Définissez les variables d'environnement pour cette étape. GITHUB_TOKEN est décrit ci-dessus.
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
Définit la valeur du champ Status sur Todo. Définit la valeur du champ Date posted.