Intégrer à la CI/CD

CodeMender peut analyser chaque demande d'extraction dans votre pipeline d'intégration et de livraison continues (CI/CD). La vérification échoue lorsque CodeMender détecte une faille de sécurité de niveau CRITICAL ou HIGH dans le code modifié par la demande d'extraction. Les résultats dans le code que la demande d'extraction n'a pas modifiés apparaissent dans le rapport, mais n'entraînent pas l'échec de la vérification.

Ce document vous explique comment :

  • Analysez les demandes d'extraction avec GitHub Actions et demandez à CodeMender d'ouvrir une demande d'extraction'extraction avec les corrections.
  • Analysez les demandes d'extraction avec Cloud Build.
  • Analysez vos modifications avant chaque commit avec un hook de pré-commit Git.

Fonctionnement des analyses des demande d'extraction d'extraction

Pour analyser une demande d'extraction d'extraction, exécutez cm find avec le flag --diff et la branche de base de la demande d'extraction :

cm find . --diff=origin/main

En réponse à cette commande, CodeMender effectue les opérations suivantes :

  1. Compare la branche de la demande d'extraction à la branche de base, et analyse les fichiers sources modifiés ainsi que les fichiers qui en dépendent directement, tels que les appelants et les importateurs.
  2. Distingue les nouvelles failles que la demande d'extraction introduit ou expose des résultats préexistants, qui sont étiquetés [LEGACY / UNTOUCHED]. Votre vérification CI ne bloque que les failles causées par la demande d'extraction.
  3. Quitte avec le code d'état 1 lorsqu'un résultat causé par la demande d'extraction d'extraction correspond à une gravité dans --fail-on. La valeur par défaut est CRITICAL,HIGH.

Pour en savoir plus sur la comparaison entre --diff et les autres modes d'analyse, consultez Modes de recherche CodeMender.

Avant de commencer

CodeMender est disponible en version Preview publique pour un nombre limité de clients. Contactez votre équipe commerciale pour y accéder.

  1. Connectez-vous à votre compte Google Cloud . Si vous débutez sur Google Cloud, créez un compte pour évaluer les performances de nos produits en conditions réelles. Les nouveaux clients bénéficient également de 300 $ de crédits sans frais pour exécuter, tester et déployer des charges de travail.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. If you're using an existing project for this guide, verify that you have the permissions required to complete this guide. If you created a new project, then you already have the required permissions.

  4. Verify that billing is enabled for your Google Cloud project.

  5. Enable the Agent Platform API and Cloud Resource Manager API APIs, if any are not already enabled.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the APIs

  6. Install the Google Cloud CLI.

  7. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  8. To initialize the gcloud CLI, run the following command:

    gcloud init
  9. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  10. If you're using an existing project for this guide, verify that you have the permissions required to complete this guide. If you created a new project, then you already have the required permissions.

  11. Verify that billing is enabled for your Google Cloud project.

  12. Enable the Agent Platform API and Cloud Resource Manager API APIs, if any are not already enabled.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the APIs

  13. Install the Google Cloud CLI.

  14. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  15. To initialize the gcloud CLI, run the following command:

    gcloud init

Assurez-vous que votre version de l'interface de ligne de commande CodeMender est compatible avec l'analyse des demande d'extraction d'extraction. Les pipelines de ce document téléchargent la dernière version stable à chaque exécution. Pour vérifier une installation locale, exécutez cm find --help et recherchez l'indicateur --diff. Pour mettre à jour la CLI, exécutez cm update. Pour en savoir plus, consultez Installer et configurer la CLI.

Rôles requis

Pour obtenir les autorisations nécessaires pour configurer des intégrations CI/CD pour CodeMender, demandez à votre administrateur de vous accorder les rôles IAM suivants sur votre projet :

Pour en savoir plus sur l'attribution de rôles, consultez Gérer l'accès aux projets, aux dossiers et aux organisations.

Vous pouvez également obtenir les autorisations requises avec des rôles personnalisés ou d'autres rôles prédéfinis.

Pour vous assurer que le compte de service CI/CD dispose des autorisations nécessaires pour exécuter CodeMender dans un pipeline CI/CD, demandez à votre administrateur d'accorder les rôles IAM suivants au compte de service CI/CD :

Pour en savoir plus sur l'attribution de rôles, consultez Gérer l'accès aux projets, aux dossiers et aux organisations.

Votre administrateur peut également attribuer au compte de service CI/CD les autorisations requises à l'aide de rôles personnalisés ou d'autres rôles prédéfinis.

Points à noter concernant la sécurité

Lorsque vous exécutez CodeMender dans un workflow GitHub Actions, un déclencheur de compilation Cloud Build ou un hook Git pre-commit, CodeMender s'exécute sans demander de confirmation. Avant de configurer ces intégrations, tenez compte des points suivants :

  • Invites de confirmation : l'indicateur --yes désactive les invites qui vous demandent de confirmer les commandes de l'agent et les écritures de fichiers. L'indicateur --bypass-warning permet d'ignorer l'avertissement indiquant que l'agent peut modifier des fichiers et exécuter des commandes sur votre système. Avant d'utiliser ces indicateurs, lisez les conditions d'utilisation de la version Preview au début de ce document, y compris celles concernant la désactivation de la confirmation humaine.
  • Bac à sable : les pipelines désactivent le bac à sable CodeMender avec --sandbox=false. Les commandes exécutées par l'agent, telles que les compilations et les tests lorsqu'il corrige un résultat, ont le même accès que le job, y compris ses identifiantsGoogle Cloud et son accès au réseau. Le bac à sable Linux utilise des espaces de noms utilisateur, que certains environnements CI, tels que les conteneurs non privilégiés, ne prennent pas en charge. Ne désactivez le bac à sable que dans des environnements isolés et jetables. Si votre environnement d'intégration continue est compatible avec le bac à sable, supprimez --sandbox=false.
  • Exécuteurs : exécutez le workflow GitHub Actions sur des exécuteurs hébergés sur GitHub, tels que ubuntu-24.04, qui exécutent chaque job dans une nouvelle machine virtuelle. N'utilisez pas de runners auto-hébergés réutilisés entre les tâches.
  • Code non fiable : le code d'une demande d'extraction peut contenir du texte qui tente d'orienter l'agent. Le workflow GitHub Actions n'analyse que les demandes d'extraction provenant de branches du même dépôt, que seuls les utilisateurs disposant d'un accès en écriture peuvent créer. Pour Cloud Build, utilisez le contrôle des commentaires afin qu'un propriétaire ou un collaborateur doive approuver les compilations pour les requêtes d'extraction d'autres contributeurs.
  • Accès : n'accordez à chaque compte de service que les rôles IAM (Identity and Access Management) requis pour son pipeline.

Analyser les demandes d'extraction avec GitHub Actions

Le workflow de cette section analyse chaque demande d'extraction d'extraction dans un dépôt sur GitHub.com. Lorsque CodeMender détecte une faille de sécurité de gravité CRITICAL ou HIGH dans les modifications de la demande d'extraction d'extraction, le workflow effectue les opérations suivantes :

  • Échec de la vérification CodeMender scan.
  • Exécute cm fix pour chaque résultat et ouvre une demande d'extraction avec les corrections dans la branche de la demande d'extraction d'extraction.

Le workflow importe également les résultats dans l'analyse du code GitHub.

Configurer la fédération d'identité de charge de travail

Le workflow s'authentifie auprès de Google Cloud avec la fédération d'identité de charge de travail. Vous n'avez donc pas besoin de stocker de clé de compte de service dans GitHub. Exécutez les commandes suivantes avec Google Cloud CLI :

  1. Définissez des variables shell pour votre projet et votre dépôt :

    PROJECT_ID="PROJECT_ID"
    GITHUB_ORG="GITHUB_ORG"
    REPO="GITHUB_ORG/REPOSITORY"
    

    Remplacez les éléments suivants :

    • PROJECT_ID : ID de votre projet Google Cloud .
    • GITHUB_ORG : nom de votre organisation GitHub ou nom d'utilisateur GitHub pour un dépôt dans un compte personnel.
    • REPOSITORY : nom de votre dépôt GitHub.
  2. Activez les API utilisées par la fédération d'identité de charge de travail :

    gcloud services enable iam.googleapis.com \
        cloudresourcemanager.googleapis.com iamcredentials.googleapis.com \
        sts.googleapis.com --project="${PROJECT_ID}"
    
  3. Créez un compte de service pour le workflow et attribuez-lui le rôle IAM Utilisateur de la plate-forme d'agent (roles/aiplatform.user) :

    gcloud iam service-accounts create codemender-ci \
        --project="${PROJECT_ID}" \
        --display-name="CodeMender CI"
    
    gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
        --member="serviceAccount:codemender-ci@${PROJECT_ID}.iam.gserviceaccount.com" \
        --role="roles/aiplatform.user"
    
  4. Créez un pool d'identités de charge de travail. Si vous disposez déjà d'un pool pour GitHub Actions, ignorez cette étape et utilisez l'ID de votre pool au lieu de github dans les étapes suivantes.

    gcloud iam workload-identity-pools create github \
        --project="${PROJECT_ID}" \
        --location="global" \
        --display-name="GitHub Actions"
    
  5. Créez un fournisseur pour GitHub dans le pool. L'attribut de condition n'accepte les jetons que des dépôts appartenant à GITHUB_ORG.

    gcloud iam workload-identity-pools providers create-oidc codemender \
        --project="${PROJECT_ID}" \
        --location="global" \
        --workload-identity-pool="github" \
        --display-name="CodeMender" \
        --attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository,attribute.repository_owner=assertion.repository_owner" \
        --attribute-condition="assertion.repository_owner == '${GITHUB_ORG}'" \
        --issuer-uri="https://token.actions.githubusercontent.com"
    
  6. Autorisez les workflows de votre dépôt à utiliser le compte de service :

    POOL_ID=$(gcloud iam workload-identity-pools describe github \
        --project="${PROJECT_ID}" \
        --location="global" \
        --format="value(name)")
    
    gcloud iam service-accounts add-iam-policy-binding \
        "codemender-ci@${PROJECT_ID}.iam.gserviceaccount.com" \
        --project="${PROJECT_ID}" \
        --role="roles/iam.workloadIdentityUser" \
        --member="principalSet://iam.googleapis.com/${POOL_ID}/attribute.repository/${REPO}"
    
  7. Obtenez le nom complet du fournisseur. Vous en aurez besoin dans la section suivante.

    gcloud iam workload-identity-pools providers describe codemender \
        --project="${PROJECT_ID}" \
        --location="global" \
        --workload-identity-pool="github" \
        --format="value(name)"
    

    La sortie ressemble à ceci :

    projects/123456789/locations/global/workloadIdentityPools/github/providers/codemender
    

La prise en compte des modifications apportées à la fédération d'identité de charge de travail et à IAM peut prendre jusqu'à cinq minutes. Pour en savoir plus, consultez Configurer la fédération d'identité de charge de travail avec des pipelines de déploiement.

Ajouter des secrets de dépôt

Dans votre dépôt, accédez à Settings > Secrets and variables > Actions (Paramètres > Secrets et variables > Actions), puis ajoutez les secrets de dépôt suivants :

Secret Valeur
GCP_PROJECT_ID L'ID de votre projet.
GCP_WIF_PROVIDER Nom complet du fournisseur indiqué dans la section précédente.
GCP_WIF_SERVICE_ACCOUNT codemender-ci@PROJECT_ID.iam.gserviceaccount.com, où PROJECT_ID correspond à l'ID de votre projet.

Pour en savoir plus, consultez Utiliser des secrets dans GitHub Actions.

Configurer les paramètres du dépôt

  1. Pour autoriser le job de correction automatique à ouvrir des demandes d'extraction, accédez à Settings (Paramètres) > Actions > General (Général). Sous Autorisations du workflow, sélectionnez Autoriser GitHub Actions à créer et approuver des demandes d'extraction, puis cliquez sur Enregistrer. Un dépôt dans une organisation hérite de ce paramètre de l'organisation. Si vous ne parvenez pas à le modifier, demandez à un propriétaire de l'organisation. Si vous n'utilisez pas la correction automatique, ignorez cette étape. Pour en savoir plus, consultez Gérer les paramètres GitHub Actions pour un dépôt.
  2. Assurez-vous que l'analyse du code GitHub est disponible pour le dépôt. Pour les dépôts privés et internes, l'analyse du code nécessite GitHub Code Security. Si l'analyse du code n'est pas disponible, supprimez l'étape Importer les résultats dans l'analyse du code ainsi que les autorisations security-events et actions du job d'analyse. Sinon, l'importation échoue, tout comme le job d'analyse. Pour en savoir plus, consultez Importer un fichier SARIF sur GitHub.

Ajouter le workflow

Effectuez un commit du workflow suivant dans votre dépôt en tant que .github/workflows/codemender.yml :

name: CodeMender

on:
  pull_request:

permissions: {}

defaults:
  run:
    shell: bash

env:
  CM_DOWNLOAD_URL: https://artifactregistry.googleapis.com/download/v1/projects/cmoc-prod/locations/us/repositories/codemender-cli-production/files/cm%3Astable%3Acm-linux-amd64.zip:download?alt=media

jobs:
  scan:
    name: CodeMender scan
    # Workflows for fork and Dependabot pull requests can't read this
    # repository's secrets, so they can't authenticate to Google Cloud.
    if: >-
      github.event.pull_request.head.repo.full_name == github.repository &&
      github.actor != 'dependabot[bot]'
    runs-on: ubuntu-24.04
    timeout-minutes: 15
    permissions:
      contents: read
      id-token: write         # Workload Identity Federation
      security-events: write  # Upload SARIF to code scanning
      actions: read           # Upload SARIF from a private repository
    outputs:
      findings: ${{ steps.scan.outputs.findings }}
    steps:
      - uses: actions/checkout@v7
        with:
          fetch-depth: 0  # cm needs the base branch history
          persist-credentials: false

      - uses: google-github-actions/auth@v3
        with:
          project_id: ${{ secrets.GCP_PROJECT_ID }}
          workload_identity_provider: ${{ secrets.GCP_WIF_PROVIDER }}
          service_account: ${{ secrets.GCP_WIF_SERVICE_ACCOUNT }}

      - name: Install the CodeMender CLI
        run: |
          curl -fsSL -o "$RUNNER_TEMP/cm.zip" "$CM_DOWNLOAD_URL"
          unzip -q -o "$RUNNER_TEMP/cm.zip" -d "$RUNNER_TEMP/cm"
          echo "$RUNNER_TEMP/cm" >> "$GITHUB_PATH"

      - name: Scan the pull request
        id: scan
        env:
          BASE_REF: ${{ github.base_ref }}
          FAIL_ON: CRITICAL,HIGH
        run: |
          cm init
          status=0
          cm find . \
            --diff="origin/$BASE_REF" \
            --diff-workers=16 \
            --fail-on="$FAIL_ON" \
            --format=sarif \
            --output=codemender.sarif \
            --sandbox=false \
            --yes \
            --bypass-warning || status=$?

          # Save the findings that failed the scan for the autofix job. Like the
          # CI gate, skip findings labeled [LEGACY / UNTOUCHED]: they're in code
          # that the pull request didn't change.
          echo '[]' > "$RUNNER_TEMP/codemender-findings.json"
          if [ "$status" -ne 0 ]; then
            cm report --format=json --status=OPEN \
              | jq --arg fail_on "$FAIL_ON" '
                  ($fail_on | ascii_upcase | split(",")) as $severities
                  | [.[]
                     | select(.title | startswith("[LEGACY / UNTOUCHED]") | not)
                     | select(.severity | ascii_upcase | IN($severities[]))]' \
              > "$RUNNER_TEMP/codemender-findings.json"
          fi
          echo "findings=$(jq length "$RUNNER_TEMP/codemender-findings.json")" >> "$GITHUB_OUTPUT"
          exit "$status"

      - name: Upload results to code scanning
        if: ${{ !cancelled() && hashFiles('codemender.sarif') != '' }}
        uses: github/codeql-action/upload-sarif@v4
        with:
          sarif_file: codemender.sarif
          category: codemender

      - name: Save findings for autofix
        if: ${{ !cancelled() && steps.scan.outputs.findings > 0 }}
        uses: actions/upload-artifact@v7
        with:
          name: codemender-findings
          path: ${{ runner.temp }}/codemender-findings.json
          retention-days: 1

  autofix:
    name: CodeMender autofix
    needs: scan
    if: ${{ !cancelled() && needs.scan.outputs.findings > 0 }}
    runs-on: ubuntu-24.04
    timeout-minutes: 60
    permissions:
      contents: write        # Push the fix branch
      pull-requests: write   # Open the fix pull request
      id-token: write        # Workload Identity Federation
    steps:
      - uses: actions/checkout@v7
        with:
          ref: ${{ github.head_ref }}
          persist-credentials: false

      - uses: google-github-actions/auth@v3
        with:
          project_id: ${{ secrets.GCP_PROJECT_ID }}
          workload_identity_provider: ${{ secrets.GCP_WIF_PROVIDER }}
          service_account: ${{ secrets.GCP_WIF_SERVICE_ACCOUNT }}

      - name: Install the CodeMender CLI
        run: |
          curl -fsSL -o "$RUNNER_TEMP/cm.zip" "$CM_DOWNLOAD_URL"
          unzip -q -o "$RUNNER_TEMP/cm.zip" -d "$RUNNER_TEMP/cm"
          echo "$RUNNER_TEMP/cm" >> "$GITHUB_PATH"

      - uses: actions/download-artifact@v8
        with:
          name: codemender-findings
          path: ${{ runner.temp }}/codemender

      - name: Fix findings
        run: |
          # Keep CodeMender state and the auth action's credentials file out of
          # the commits, and out of the `git clean` that cm fix runs.
          printf '%s\n' .cm_project 'gha-creds-*.json' >> .git/info/exclude

          cm init
          # Fix in the repository root instead of each file's directory.
          printf 'project_paths:\n  - "%s"\n' "$GITHUB_WORKSPACE" \
            >> ~/.codemender/config.yaml
          cm report import -f "$RUNNER_TEMP/codemender/codemender-findings.json"

          git config user.name "github-actions[bot]"
          git config user.email \
            "41898282+github-actions[bot]@users.noreply.github.com"

          cm report --format=json --status=OPEN \
            | jq -r '.[] | [.finding_id, .title] | @tsv' \
            > "$RUNNER_TEMP/findings.tsv"
          while IFS=$'\t' read -r id title; do
            # cm fix exits 0 when it makes no edits, so also check for changes.
            if cm fix "$id" \
                 --sandbox=false --yes --bypass-warning < /dev/null &&
               ! git diff --quiet; then
              git commit -q -a -m "Fix $title" -m "CodeMender finding $id"
            else
              echo "::warning::CodeMender didn't fix \"$title\" ($id)."
            fi
            # Discard files the fix agent created, such as test output.
            git reset -q --hard
            git clean -q -fd
          done < "$RUNNER_TEMP/findings.tsv"

      - uses: peter-evans/create-pull-request@v8
        with:
          branch: codemender/fix-pr-${{ github.event.pull_request.number }}
          base: ${{ github.head_ref }}
          title: "CodeMender fixes for #${{ github.event.pull_request.number }}"
          body: |
            CodeMender generated these fixes for findings in #${{ github.event.pull_request.number }}.
            Review each commit before you merge this pull request into `${{ github.head_ref }}`.

Détails du workflow

Le schéma suivant montre comment interagissent les tâches d'analyse et de correction automatique des demande d'extraction d'extraction :

Une demande d'extraction est analysée. Si aucun résultat bloquant n'est détecté, la vérification est réussie. Sinon, la vérification échoue, CodeMender ouvre une demande d'extraction de correctif et la fusion des correctifs analyse à nouveau la demande d'extraction;extraction.

Le job CodeMender scan effectue les opérations suivantes :

  1. Extrait la demande d'extraction avec son historique complet. Pour les demandes d'extraction, GitHub extrait un commit de fusion de la branche de la demande d'extraction d'extraction dans la branche de base.
  2. S'authentifie auprès de Google Cloud et télécharge la dernière version stable de la CLI CodeMender.
  3. Exécute cm find --diff sur la branche de base. La tâche échoue si CodeMender détecte une faille dont la gravité est indiquée dans FAIL_ON dans les modifications de la demande d'extraction.
  4. Importe le rapport dans l'analyse du code GitHub, même si l'analyse échoue. Le rapport inclut les résultats portant le libellé [LEGACY / UNTOUCHED]. L'analyse du code affiche également un résultat dans les vérifications de la demande d'extraction d'extraction lorsque toutes les lignes du résultat se trouvent dans le diff de la demande d'extraction d'extraction.
  5. Enregistre les résultats qui ont échoué au job de correction automatique.

Le job d'analyse ne s'exécute pas pour les demandes d'extraction à partir de forks ou de Dependabot, car les workflows pour ces demandes d'extraction ne peuvent pas lire les secrets du dépôt. GitHub indique qu'un job ignoré a réussi. La vérification ne bloque donc pas ces demandes d'extraction, même si vous en faites une vérification obligatoire. Examinez vous-même ces requêtes d'extraction ou analysez-les localement avec cm find --diff.

Le job CodeMender autofix s'exécute lorsque le job d'analyse enregistre les résultats. Elle effectue les opérations suivantes :

  1. Extrait la branche de la demande d'extraction.
  2. Exécute cm fix pour chaque résultat et valide chaque correction séparément. Si CodeMender ne corrige pas un résultat, le job enregistre un avertissement. Le job n'enregistre que les modifications apportées aux fichiers qui se trouvent déjà dans le dépôt et supprime tous les fichiers créés par l'agent de correction, tels que les résultats des tests.
  3. Ouvre une demande d'extraction à partir de la branche codemender/fix-pr-NUMBER dans la branche de demande d'extraction, où NUMBER correspond au numéro de la demande d'extraction d'extraction. Si la demande d'extraction de correctif existe déjà, le job la met à jour. Si CodeMender ne corrige aucun problème ou si le job atteint son délai de 60 minutes, aucune demande d'extraction n'est ouverte.

Examiner et fusionner les corrections

GitHub n'exécute pas automatiquement les workflows pour les demandes d'extraction qu'un workflow crée avec GITHUB_TOKEN. Pour analyser la demande d'extraction correction, un utilisateur disposant d'un accès en écriture au dépôt clique sur Approuver l'exécution des workflows dans la demande d'extraction de correction.

Lorsque vous fusionnez la demande d'extraction de correction, la branche de la demande d'extraction d'extraction change et le workflow analyse à nouveau la demande d'extraction d'origine.

Personnaliser le workflow

Vous pouvez personnaliser le workflow de différentes manières :

  • Pour modifier les niveaux de gravité qui échouent à la vérification, dans l'étape Analyser la demande d'extraction, définissez FAIL_ON sur une liste de niveaux de gravité séparés par une virgule, sans espaces, par exemple CRITICAL,HIGH,MEDIUM. Les valeurs valides sont CRITICAL, HIGH, MEDIUM et LOW.
  • Pour signaler des résultats sans échec du contrôle, définissez FAIL_ON: "". Le workflow continue d'importer les résultats dans l'analyse du code, mais il n'exécute pas le job de correction automatique.
  • Pour n'analyser les requêtes pull que dans certaines branches, ajoutez un filtre branches au déclencheur pull_request. Le workflow n'analyse ensuite pas les demandes d'extraction de correctifs, car leur base est une branche de demande d'extraction d'extraction :

    on:
      pull_request:
        branches: [main]
    
  • Pour désactiver la correction automatique, supprimez le job autofix et l'étape Enregistrer les résultats pour la correction automatique.

Analyser les demandes d'extraction avec Cloud Build

La compilation de cette section analyse chaque demande d'extraction d'extraction dans un dépôt GitHub connecté à Cloud Build. La compilation et sa vérification GitHub échouent lorsque CodeMender détecte une faille de gravité CRITICAL ou HIGH dans les modifications de la demande d'extraction. La compilation ne corrige pas les résultats.

Avant de commencer, procédez comme suit :

  1. Connectez votre dépôt à Cloud Build en tant que dépôt de deuxième génération. Pour en savoir plus, consultez Se connecter à un dépôt GitHub.
  2. Activez les API Cloud Build et IAM dans le projet qui a accès à CodeMender. La compilation utilise CodeMender dans le projet qui exécute la compilation.

    PROJECT_ID="PROJECT_ID"
    gcloud services enable cloudbuild.googleapis.com iam.googleapis.com \
        --project="${PROJECT_ID}"
    

    Remplacez PROJECT_ID par l'ID de votre projet Google Cloud.

Créer un compte de service

Créez un compte de service pour la compilation. Accordez-lui le rôle IAM Utilisateur Agent Platform (roles/aiplatform.user) pour utiliser CodeMender et le rôle Rédacteur de journaux (roles/logging.logWriter) pour écrire les journaux de compilation :

SA="codemender-build@${PROJECT_ID}.iam.gserviceaccount.com"

gcloud iam service-accounts create codemender-build \
    --project="${PROJECT_ID}" \
    --display-name="CodeMender Cloud Build"

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:${SA}" \
    --role="roles/aiplatform.user"

gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
    --member="serviceAccount:${SA}" \
    --role="roles/logging.logWriter"

Pour enregistrer les rapports SARIF dans un bucket Cloud Storage, accordez également l'accès au bucket au compte de service :

BUCKET="BUCKET"

gcloud storage buckets add-iam-policy-binding "gs://${BUCKET}" \
    --member="serviceAccount:${SA}" \
    --role="roles/storage.objectUser"

Remplacez BUCKET par le nom de votre bucket Cloud Storage.

Ajouter la configuration de compilation

Validez la configuration de compilation suivante à la racine de votre dépôt sous le nom cloudbuild.yaml :

# Scans a pull request with CodeMender. The build fails when CodeMender finds
# a CRITICAL or HIGH vulnerability in the pull request's changes.
steps:
  - id: install-codemender
    name: gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
    script: |
      #!/usr/bin/env bash
      set -euo pipefail
      curl -fsSL -o /tmp/cm.zip "$_CM_DOWNLOAD_URL"
      python3 -m zipfile -e /tmp/cm.zip /workspace/.codemender-cli
      chmod +x /workspace/.codemender-cli/cm

  - id: fetch-history
    name: gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
    script: |
      #!/usr/bin/env bash
      set -euo pipefail
      : "${_BASE_BRANCH:?Run this build from a pull request trigger.}"
      # Triggers check out only the pull request's commit. CodeMender needs the
      # history back to where the pull request branched from the base branch.
      # Fetch from origin, or from GitHub if origin isn't configured.
      refspec="+refs/heads/$_BASE_BRANCH:refs/remotes/origin/$_BASE_BRANCH"
      git fetch --quiet --unshallow origin "$refspec" ||
        git fetch --quiet --unshallow \
          "https://github.com/$REPO_FULL_NAME.git" "$refspec"
      merge_base=$(git merge-base HEAD "origin/$_BASE_BRANCH")
      echo "Merge base with $_BASE_BRANCH: $merge_base"

  - id: scan
    name: gcr.io/google.com/cloudsdktool/google-cloud-cli:slim
    script: |
      #!/usr/bin/env bash
      set -uo pipefail
      export PATH="/workspace/.codemender-cli:$PATH"
      # The project that has access to CodeMender.
      export GOOGLE_CLOUD_PROJECT="$PROJECT_ID"
      cm init || exit 1
      status=0
      cm find . \
        --diff="origin/$_BASE_BRANCH" \
        --diff-workers=16 \
        --fail-on=CRITICAL,HIGH \
        --format=sarif \
        --output=codemender.sarif \
        --sandbox=false \
        --yes \
        --bypass-warning || status=$?

      # cm find writes the SARIF report when the scan completes.
      if [ -f codemender.sarif ]; then
        # cm find doesn't print finding details, so print them here.
        cm report --status=OPEN --format=md
        if [ -n "${_REPORT_BUCKET:-}" ]; then
          gcloud storage cp codemender.sarif \
            "gs://$_REPORT_BUCKET/codemender/$BUILD_ID.sarif" || status=1
        fi
      fi
      exit "$status"

substitutions:
  _CM_DOWNLOAD_URL: https://artifactregistry.googleapis.com/download/v1/projects/cmoc-prod/locations/us/repositories/codemender-cli-production/files/cm%3Astable%3Acm-linux-amd64.zip:download?alt=media
  _REPORT_BUCKET: ''  # Optional: a bucket to save the SARIF report in.

timeout: 1200s
options:
  automapSubstitutions: true
  logging: CLOUD_LOGGING_ONLY

Créer le déclencheur

Créez un déclencheur qui exécute la compilation pour chaque demande d'extraction#39;extraction dans main :

REGION="REGION"
CONNECTION="CONNECTION"
REPOSITORY="REPOSITORY"

gcloud builds triggers create github \
    --project="${PROJECT_ID}" \
    --region="${REGION}" \
    --name="codemender-scan" \
    --repository="projects/${PROJECT_ID}/locations/${REGION}/connections/${CONNECTION}/repositories/${REPOSITORY}" \
    --pull-request-pattern='^main$' \
    --comment-control=COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY \
    --build-config=cloudbuild.yaml \
    --service-account="projects/${PROJECT_ID}/serviceAccounts/${SA}"

Remplacez les éléments suivants :

  • REGION : région de votre connexion au dépôt Cloud Build.
  • CONNECTION : nom de votre connexion au dépôt Cloud Build.
  • REPOSITORY : nom du dépôt connecté dans Cloud Build.

Notez les options suivantes :

  • --pull-request-pattern est une expression régulière pour la branche de base de la demande d'extraction d'extraction. Utilisez ^ et $ pour faire correspondre l'intégralité du nom de la branche.
  • Avec --comment-control=COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY, la compilation s'exécute automatiquement pour les demandes d'extraction des propriétaires et des collaborateurs du dépôt. Pour les demandes d'extraction d'autres contributeurs, la compilation s'exécute après qu'un propriétaire ou un collaborateur a commenté /gcbrun la demande d'extraction d'extraction.
  • Pour enregistrer les rapports SARIF dans un bucket, ajoutez --substitutions=_REPORT_BUCKET="${BUCKET}".

Vous pouvez également créer le déclencheur dans la console Google Cloud . Pour en savoir plus, consultez Créer des dépôts à partir de GitHub.

Pour afficher les journaux de compilation dans GitHub, ajoutez --include-logs-with-status lorsque vous créez le déclencheur, puis accordez le rôle Lecteur de journaux (roles/logging.viewer) au compte de service. Toute personne pouvant consulter la vérification dans GitHub peut alors lire les journaux de compilation, y compris les résultats.

Fonctionnement de la compilation

Le build comporte trois étapes :

  1. install-codemender télécharge la dernière version stable de CLI commande CodeMender.
  2. fetch-history récupère la branche de base et l'historique dont CodeMender a besoin. Cloud Build n'extrait que le commit qui a lancé la compilation. L'étape extrait les données du dépôt distant origin. Si origin n'est pas configuré, l'étape récupère les données depuis GitHub sans identifiants, ce qui ne fonctionne que pour les dépôts publics. Dans ce cas, un dépôt privé a besoin d'identifiants, comme une clé SSH. Pour en savoir plus, consultez Accéder à GitHub à partir d'une compilation à l'aide de clés SSH.
  3. scan exécute cm find --diff par rapport à la branche de base. Une fois l'analyse terminée, l'étape imprime tous les résultats dans le journal de compilation. Si vous définissez _REPORT_BUCKET, l'étape copie également le rapport SARIF dans gs://BUCKET/codemender/BUILD_ID.sarif.

Pour modifier les niveaux de gravité qui entraînent l'échec de la compilation, modifiez --fail-on dans l'étape scan. Si vous exécutez la compilation sans déclencheur de demande d'extraction;extraction, elle échoue et affiche le message Run this build from a pull request trigger..

Analyser avant chaque commit

Un hook de pré-commit Git peut analyser vos modifications préparées et bloquer le commit lorsque CodeMender détecte une faille de gravité CRITICAL ou HIGH. Les développeurs peuvent ignorer le crochet. Utilisez-le donc en plus de l'analyse dans l'intégration continue, et non à la place.

Chaque développeur qui utilise le crochet a besoin des éléments suivants :

  • La CLI CodeMender, installée et configurée comme décrit dans Installer et configurer la CLI, y compris gcloud auth application-default login et cm init. Le crochet a besoin de cm sur le PATH.
  • Le rôle Utilisateur Agent Platform (roles/aiplatform.user) dans un projet ayant accès à CodeMender. CodeMender utilise le projet dans la variable d'environnement GOOGLE_CLOUD_PROJECT. Si cette variable n'est pas définie, CodeMender utilise le projet de vos Identifiants par défaut de l'application ou votre projet par défaut gcloud CLI.

Pour ajouter le hook, enregistrez le script suivant sous le nom .git/hooks/pre-commit dans votre dépôt :

#!/bin/sh
# Scans staged changes with CodeMender before each commit.
if ! cm find . --diff --staged --fail-on=CRITICAL,HIGH \
    --yes --bypass-warning; then
  echo "CodeMender blocked this commit. To see the findings, run:" >&2
  echo "  cm report --status=OPEN" >&2
  echo "To commit anyway, run git commit --no-verify." >&2
  exit 1
fi

Rendez le script exécutable, puis ajoutez .cm_project à votre fichier .gitignore afin de ne pas valider le fichier créé par CodeMender pour suivre le dépôt :

chmod +x .git/hooks/pre-commit
echo .cm_project >> .gitignore

Lorsque vous exécutez git commit, le hook analyse les fichiers avec les modifications mises en scène. L'analyse peut prendre quelques minutes. Le crochet ne désactive pas le bac à sable CodeMender.

Pour valider sans analyse, exécutez git commit --no-verify.

Indicateurs d'analyse

Les options cm find suivantes contrôlent les analyses des demande d'extraction d'extraction. Pour tous les indicateurs, exécutez cm find --help :

Option Valeur par défaut Description
--diff[=REF] Désactivé Analyse les modifications par rapport à REF, par exemple origin/main. Sans REF, les analyses valident les modifications non validées apportées aux fichiers suivis (par rapport à HEAD). Ne peut pas être utilisé avec --deep.
--staged Désactivé Avec --diff, les modifications mises en scène sont les seules à être analysées.
--diff-depth DEPTH 1 Profondeur de parcours pour l'analyse d'impact (de 1 à 3, par défaut : 1 saut).
--diff-workers COUNT 4 Nombre de fichiers à analyser en même temps (de 1 à 16).
--diff-max-neighbors COUNT 10 Nombre maximal de fichiers dépendants à analyser.
--fail-on SEVERITIES CRITICAL,HIGH Avec --diff, les niveaux de gravité qui font que cm find quitte avec l'état 1. Si la valeur est vide, les résultats n'ont aucune incidence sur l'état de sortie.
--fail-on-truncation Désactivé Avec --diff, le programme se ferme avec l'état 1 si CodeMender trouve plus de fichiers dépendants que --diff-max-neighbors ne le permet.
--format FORMAT table Format du rapport : table, json ou sarif.
--output FILE Sortie standard Fichier dans lequel écrire le rapport.

Dépannage

Cette section explique comment résoudre les problèmes courants lors de l'exécution de CodeMender dans des pipelines CI/CD.

Autorisation refusée

Le journal affiche une ligne semblable à celle-ci :

[1/1] ❌ src/app.py: start session failed: StartSession failed with HTTP 403 Forbidden.

Le message peut également inclure Permission 'aiplatform.interactions.create' denied. Vérifiez les éléments suivants :

  • Le projet a accès à CodeMender.
  • Le compte de service ou l'utilisateur dispose du rôle Utilisateur Agent Platform (roles/aiplatform.user) dans le projet.
  • L'API Agent Platform est activée dans le projet.
  • CodeMender utilise le bon projet. Dans GitHub Actions, vérifiez le secret GCP_PROJECT_ID. Cloud Build utilise le projet qui exécute le build. En local, vérifiez la variable d'environnement GOOGLE_CLOUD_PROJECT ou votre projet par défaut si la variable n'est pas définie.

Configuration des ressources en cours

Si le journal affiche Resource setup has just started. Please try again shortly. ou Resource setup is in progress. Please try again shortly., CodeMender configure les ressources pour votre projet, ce qui prend généralement quelques minutes. Exécutez à nouveau le job plus tard.

Indicateur inconnu : --diff

Si cm find échoue avec Error: unknown flag: --diff, votre version de la CLI ne prend pas en charge les analyses des demande d'extraction d'extraction. Exécutez cm update ou téléchargez la dernière version.

Branche de base introuvable

Si cm find échoue et affiche une erreur semblable à celle-ci, cela signifie que la branche de base n'est pas dans l'extraction :

Error: retrieving VCS diff: git diff failed: exit status 128: fatal: ambiguous argument 'origin/main': unknown revision or path not in the working tree.

Récupérez la branche de base et son historique avant d'exécuter cm find. Dans GitHub Actions, définissez fetch-depth: 0 dans actions/checkout.

Fichiers non analysés

Une ligne avec ❌, comme [1/1] ❌ src/app.py: start session failed, signifie que CodeMender n'a pas pu analyser ce fichier. Vérifiez l'erreur dans la ligne, puis exécutez à nouveau le job.

Aucune demande d'extraction de correction

Si le workflow n'ouvre pas de demande d'extraction de correctif, vérifiez les points suivants :

  • Si le job de correction automatique échoue lors de la création de la demande d'extraction d'extraction, activez l'option Autoriser GitHub Actions à créer et approuver des demandes d'extraction. Pour en savoir plus, consultez Configurer les paramètres du dépôt.
  • Si le job de correction automatique réussit sans ouvrir de demande d'extraction d'extraction, cela signifie que CodeMender n'a corrigé aucun résultat. Le journal des tâches affiche un avertissement pour chaque résultat que CodeMender n'a pas corrigé.

Échec de l'importation de l'analyse du code

Si l'étape d'importation échoue avec GitHub Code Security or GitHub Advanced Security must be enabled for this repository to use code scanning, activez GitHub Code Security pour le dépôt ou supprimez l'étape d'importation. Pour en savoir plus, consultez Configurer les paramètres du dépôt.

Avertissement non confirmé

Si cm échoue avec warning not acknowledged. Please run interactively once to acknowledge or pass --bypass-warning, CodeMender a besoin d'une confirmation qu'il ne peut pas demander dans un environnement non interactif. Ajoutez --bypass-warning à la commande. Avant de le faire, lisez les conditions d'aperçu en haut de cette page.

Pour obtenir de l'aide, contactez votre équipe commerciale.