Integrar com CI/CD

O CodeMender pode verificar cada solicitação de envio no pipeline de integração e entrega contínua (CI/CD). A verificação falha quando o CodeMender encontra uma vulnerabilidade com gravidade CRITICAL ou HIGH no código que a solicitação de extração muda. As descobertas no código que a solicitação de envio não mudou aparecem no relatório, mas não falham na verificação.

Esta página mostra como fazer o seguinte:

  • Verifique as solicitações de pull com o GitHub Actions e faça com que o CodeMender abra uma solicitação de envio com correções.
  • Verificar solicitações de pull com o Cloud Build.
  • Verifique as mudanças antes de cada commit com um hook de pré-commit do Git.

Como funcionam as verificações de solicitação de envio

Para verificar uma solicitação de envio, execute cm find com a flag --diff e a ramificação base da solicitação de pull:

cm find . --diff=origin/main

Em resposta a esse comando, o CodeMender faz o seguinte:

  1. Compara a ramificação do solicitação de envio com a ramificação de base e verifica os arquivos de origem modificados e os arquivos que dependem diretamente deles, como chamadores e importadores.
  2. Distingue novas vulnerabilidades introduzidas ou expostas pela solicitação de envio de descobertas preexistentes, que são rotuladas como [LEGACY / UNTOUCHED]. A verificação de CI bloqueia apenas vulnerabilidades causadas pela solicitação de extração.
  3. Sai com o status 1 quando uma descoberta causada pela solicitação de envio corresponde a uma gravidade em --fail-on. O padrão é CRITICAL,HIGH.

Para mais informações sobre como o --diff se compara a outros modos de verificação, consulte Modos de localização do CodeMender.

Antes de começar

O CodeMender está disponível para um grupo limitado de clientes no Acesso antecipado. Entre em contato com sua equipe de vendas para ter acesso.

  1. Faça login na sua conta do Google Cloud . Se você começou a usar o Google Cloudagora, crie uma conta para avaliar o desempenho dos nossos produtos em situações reais. Clientes novos também recebem US $300 em créditos para executar, testar e implantar cargas de trabalho.
  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

Confira se a versão da CLI do CodeMender é compatível com verificações de solicitação de envio. Os pipelines neste documento baixam a versão estável mais recente sempre que são executados. Para verificar uma instalação local, execute cm find --help e procure a flag --diff. Para atualizar a CLI, execute cm update. Para mais informações, consulte Instalar e configurar a CLI.

Funções exigidas

Para receber as permissões necessárias para configurar integrações de CI/CD para o CodeMender, peça ao administrador para conceder a você os seguintes papéis do IAM no projeto:

Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.

Também é possível conseguir as permissões necessárias usando papéis personalizados ou outros papéis predefinidos.

Para garantir que a conta de serviço de CI/CD tenha as permissões necessárias para executar o CodeMender em um pipeline de CI/CD, peça ao administrador para conceder os seguintes papéis do IAM à conta de serviço de CI/CD:

Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.

O administrador também pode conceder à conta de serviço de CI/CD as permissões necessárias por meio de papéis personalizados ou outros papéis predefinidos.

Considerações sobre segurança

Quando você executa o CodeMender em um fluxo de trabalho do GitHub Actions, um gatilho de build do Cloud Build ou um hook de pré-commit do Git, o CodeMender é executado sem pedir confirmação. Antes de configurar essas integrações, considere o seguinte:

  • Solicitações de confirmação: a flag --yes desativa as solicitações de confirmação dos comandos do agente e gravações de arquivos. A flag --bypass-warning ignora o aviso de que o agente pode modificar arquivos e executar comandos no sistema. Antes de usar essas flags, leia os termos de prévia no início deste documento, incluindo os termos sobre a desativação da confirmação humana.
  • Sandbox: os pipelines desativam o sandbox do CodeMender com --sandbox=false. Os comandos executados pelo agente, como builds e testes quando ele corrige uma descoberta, têm o mesmo acesso que o job, incluindo as credenciais e o acesso à redeGoogle Cloud . O sandbox do Linux usa namespaces de usuário, que alguns ambientes de CI, como contêineres sem privilégios, não oferecem suporte. Desative o sandbox apenas em ambientes isolados e descartáveis. Se o ambiente de CI for compatível com a sandbox, remova --sandbox=false.
  • Executores: execute o fluxo de trabalho do GitHub Actions em executores hospedados no GitHub, como ubuntu-24.04, que executam cada job em uma nova máquina virtual. Não use executores autohospedados que sejam reutilizados entre jobs.
  • Código não confiável: o código em uma solicitação de envio pode conter texto que tenta direcionar o agente. O fluxo de trabalho do GitHub Actions verifica apenas solicitações de pull de ramificações no mesmo repositório, que só podem ser criadas por usuários com acesso de gravação. Para o Cloud Build, use o controle de comentários para que um proprietário ou colaborador precise aprovar builds para solicitações de pull de outros colaboradores.
  • Acesso: conceda a cada conta de serviço apenas os papéis necessários do Identity and Access Management (IAM) para o pipeline.

Verificar solicitações de pull com o GitHub Actions

O fluxo de trabalho nesta seção verifica cada solicitação de envio em um repositório no GitHub.com. Quando o CodeMender encontra uma vulnerabilidade com gravidade CRITICAL ou HIGH nas mudanças da solicitação de envio, o fluxo de trabalho faz o seguinte:

  • Falha na verificação da verificação do CodeMender.
  • Executa cm fix para cada descoberta e abre uma solicitação de envio com as correções na ramificação da solicitação de envio.

O fluxo de trabalho também faz upload das descobertas para a verificação de código do GitHub.

Configurar a federação de identidade da carga de trabalho

O fluxo de trabalho faz a autenticação no Google Cloud com a federação de identidade da carga de trabalho. Assim, você não precisa armazenar uma chave da conta de serviço no GitHub. Execute os seguintes comandos com a Google Cloud CLI:

  1. Defina variáveis de shell para seu projeto e repositório:

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

    Substitua:

    • PROJECT_ID: o ID do projeto Google Cloud .
    • GITHUB_ORG: o nome da sua organização do GitHub ou seu nome de usuário do GitHub para um repositório em uma conta pessoal.
    • REPOSITORY: o nome do seu repositório do GitHub.
  2. Ative as APIs usadas pela federação de identidade da carga de trabalho:

    gcloud services enable iam.googleapis.com \
        cloudresourcemanager.googleapis.com iamcredentials.googleapis.com \
        sts.googleapis.com --project="${PROJECT_ID}"
    
  3. Crie uma conta de serviço para o fluxo de trabalho e conceda a ela o papel do IAM de usuário da plataforma do agente (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. Crie um pool de identidade da carga de trabalho. Se você já tiver um pool para o GitHub Actions, pule esta etapa e use o ID do seu pool em vez de github nas etapas a seguir.

    gcloud iam workload-identity-pools create github \
        --project="${PROJECT_ID}" \
        --location="global" \
        --display-name="GitHub Actions"
    
  5. Crie um provedor para o GitHub no pool. A condição de atributo aceita tokens apenas de repositórios que o GITHUB_ORG possui.

    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. Permita que os fluxos de trabalho no seu repositório usem a conta de serviço:

    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. Acesse o nome completo do provedor. Você precisará dele na próxima seção.

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

    A saída será assim:

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

As mudanças na federação de identidade da carga de trabalho e no IAM podem levar até 5 minutos para entrar em vigor. Para mais informações, consulte Configurar a federação de identidade da carga de trabalho com pipelines de implantação.

Adicionar secrets do repositório

No seu repositório, acesse Configurações > Segredos e variáveis > Ações e adicione os seguintes segredos do repositório:

Secret Valor
GCP_PROJECT_ID O ID do projeto.
GCP_WIF_PROVIDER O nome completo do provedor da seção anterior.
GCP_WIF_SERVICE_ACCOUNT codemender-ci@PROJECT_ID.iam.gserviceaccount.com, em que PROJECT_ID é o ID do projeto.

Para mais informações, consulte Como usar secrets no GitHub Actions.

Configurar as definições do repositório

  1. Para permitir que o trabalho de correção automática abra solicitações de pull, acesse Configurações > Ações > Geral. Em Permissões de fluxo de trabalho, selecione Permitir que o GitHub Actions crie e aprove solicitações de envio e clique em Salvar. Um repositório em uma organização herda essa configuração da organização. Se não for possível mudar, peça ajuda a um proprietário da organização. Se você não usa a correção automática, pule esta etapa. Para mais informações, consulte Gerenciar as configurações do GitHub Actions para um repositório.
  2. Verifique se a verificação de código do GitHub está disponível para o repositório. Para repositórios particulares e internos, a verificação de código exige o GitHub Code Security. Se a verificação de código não estiver disponível, exclua a etapa Fazer upload dos resultados para a verificação de código e as permissões security-events e actions do job de verificação. Caso contrário, o upload e o job de verificação vão falhar. Para mais informações, consulte Fazer upload de um arquivo SARIF para o GitHub.

Adicionar o fluxo de trabalho

Confirme o seguinte fluxo de trabalho no repositório como .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 }}`.

Detalhes do fluxo de trabalho

O diagrama a seguir mostra como os trabalhos de verificação e correção automática de solicitação de envio interagem:

Uma solicitação de envio é verificada. Se não houver indícios de bloqueio, a verificação será aprovada. Caso contrário, a verificação falha, o CodeMender abre uma solicitação de envio de correção, e a fusão das correções verifica a solicitação de envio novamente.

O job verificação do CodeMender faz o seguinte:

  1. Confira a solicitação de envio com o histórico completo. Para solicitações de pull, o GitHub faz o check-out de um commit de mesclagem da ramificação da solicitação de envio para a ramificação base.
  2. Faz a autenticação no Google Cloud e baixa a versão estável mais recente da CLI do CodeMender.
  3. Executa cm find --diff no branch de base. O job falha se o CodeMender encontrar uma vulnerabilidade com uma gravidade listada em FAIL_ON nas mudanças do solicitação de pull.
  4. Faz upload do relatório para a verificação de código do GitHub, mesmo quando a verificação falha no job. O relatório inclui descobertas rotuladas como [LEGACY / UNTOUCHED]. A verificação de código também mostra uma descoberta nas verificações da solicitação de envio quando todas as linhas da descoberta estão no diff da solicitação de envio.
  5. Salva as descobertas que falharam no job de correção automática.

O job de verificação não é executado para solicitações de pull de forks ou do Dependabot, porque os fluxos de trabalho dessas solicitações não podem ler os segredos do repositório. O GitHub informa um job ignorado como bem-sucedido. Portanto, a verificação não bloqueia essas solicitações de pull, mesmo que você a torne obrigatória. Analise esses pull requests ou verifique-os localmente com cm find --diff.

O job de correção automática do CodeMender é executado quando o job de verificação salva descobertas. Ele faz o seguinte:

  1. Faz o check-out da ramificação da solicitação de envio.
  2. Executa cm fix para cada descoberta e confirma cada correção separadamente. Se o CodeMender não corrigir uma descoberta, o job vai registrar um aviso. O job confirma apenas mudanças em arquivos que já estão no repositório e descarta qualquer arquivo criado pelo agente de correção, como a saída de teste.
  3. Abre uma solicitação de envio da ramificação codemender/fix-pr-NUMBER para a ramificação de solicitação de pull, em que NUMBER é o número da solicitação de envio. Se a solicitação de envio de correção já existir, o job vai atualizá-la. Se o CodeMender não corrigir nenhum problema ou se o trabalho atingir o tempo limite de 60 minutos, ele não vai abrir uma solicitação de envio.

Revisar e mesclar correções

O GitHub não executa automaticamente fluxos de trabalho para solicitações de envio que um fluxo de trabalho cria com o GITHUB_TOKEN. Para verificar a solicitação de envio da correção, um usuário com acesso de gravação ao repositório clica em Aprovar fluxos de trabalho para execução na solicitação de pull da correção.

Quando você mescla a solicitação de envio de correção, a ramificação da solicitação de envio muda, e o fluxo de trabalho verifica a solicitação de envio original novamente.

Personalizar o fluxo de trabalho

É possível personalizar o fluxo de trabalho das seguintes maneiras:

  • Para mudar as gravidades que falham na verificação, na etapa Verificar a solicitação de pull, defina FAIL_ON como uma lista separada por vírgulas de gravidades sem espaços, como CRITICAL,HIGH,MEDIUM. Os valores válidos são CRITICAL, HIGH, MEDIUM e LOW.
  • Para informar descobertas sem falhar na verificação, defina FAIL_ON: "". O fluxo de trabalho ainda faz upload de descobertas para a verificação de código, mas não executa o job de correção automática.
  • Para verificar solicitações de pull em apenas algumas ramificações, adicione um filtro branches ao acionador pull_request. O fluxo de trabalho não verifica solicitações de pull de correção, porque a base delas é uma ramificação de solicitação de envio:

    on:
      pull_request:
        branches: [main]
    
  • Para desativar a correção automática, exclua o job autofix e a etapa Salvar descobertas para correção automática.

Verificar solicitações de pull com o Cloud Build

O build nesta seção verifica cada solicitação de envio em um repositório do GitHub conectado ao Cloud Build. O build e a verificação do GitHub falham quando o CodeMender encontra uma vulnerabilidade com gravidade CRITICAL ou HIGH nas mudanças do pull request. O build não corrige as descobertas.

Antes de começar, faça o seguinte:

  1. Conecte seu repositório ao Cloud Build como um repositório de segunda geração. Para mais informações, consulte Conectar a um repositório do GitHub.
  2. Ative a API Cloud Build e a API IAM no projeto que tem acesso ao CodeMender. O build usa o CodeMender no projeto que executa o build.

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

    Substitua PROJECT_ID pelo ID do projeto do Google Cloud.

Criar uma conta de serviço

Crie uma conta de serviço para o build. Conceda a ela o papel do IAM de usuário da Agent Platform (roles/aiplatform.user) para usar o CodeMender e o papel de gravador de registros (roles/logging.logWriter) para gravar registros de build:

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"

Para salvar relatórios SARIF em um bucket do Cloud Storage, conceda à conta de serviço acesso ao bucket:

BUCKET="BUCKET"

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

Substitua BUCKET pelo nome do bucket do Cloud Storage.

Adicionar a configuração de build

Faça commit da seguinte configuração de build na raiz do repositório como 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

Criar o gatilho

Crie um gatilho que execute o build para cada solicitação de envio em 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}"

Substitua:

  • REGION: a região da conexão do repositório do Cloud Build.
  • CONNECTION: o nome da conexão do repositório do Cloud Build.
  • REPOSITORY: o nome do repositório conectado no Cloud Build.

Observações:

  • --pull-request-pattern é uma expressão regular para a ramificação base da solicitação de envio. Use ^ e $ para corresponder ao nome completo da ramificação.
  • Com o --comment-control=COMMENTS_ENABLED_FOR_EXTERNAL_CONTRIBUTORS_ONLY, o build é executado automaticamente para solicitações de envio de proprietários e colaboradores do repositório. Para solicitações de pull de outros colaboradores, o build é executado depois que um proprietário ou colaborador comenta /gcbrun na solicitação de envio.
  • Para salvar relatórios SARIF em um bucket, adicione --substitutions=_REPORT_BUCKET="${BUCKET}".

Também é possível criar o gatilho no console Google Cloud . Para mais informações, consulte Como criar repositórios no GitHub.

Para mostrar os registros de build no GitHub, adicione --include-logs-with-status ao criar o gatilho e conceda à conta de serviço o papel de leitor de registros (roles/logging.viewer). Assim, qualquer pessoa que possa ver a verificação no GitHub poderá ler os registros de build, incluindo as descobertas.

Como o build funciona

O build tem três etapas:

  1. install-codemender baixa a versão estável mais recente da CLI do CodeMender.
  2. O fetch-history busca a ramificação de base e o histórico necessários para o CodeMender. O Cloud Build faz o check-out apenas do commit que iniciou o build. A etapa busca do origin remoto. Se origin não estiver configurado, a etapa vai buscar informações do GitHub sem credenciais, o que só funciona para repositórios públicos. Nesse caso, um repositório particular precisa de credenciais, como uma chave SSH. Para mais informações, consulte Como acessar o GitHub de um build usando chaves SSH.
  3. O scan executa cm find --diff na ramificação de base. Quando a verificação é concluída, a etapa imprime todas as descobertas no registro de build. Se você definir _REPORT_BUCKET, a etapa também vai copiar o relatório SARIF para gs://BUCKET/codemender/BUILD_ID.sarif.

Para mudar as gravidades que falham na build, edite --fail-on na etapa scan. Se você executar o build sem um gatilho de solicitação de envio, ele vai falhar com a mensagem Run this build from a pull request trigger.

Verificar antes de cada commit

Um hook de pré-commit do Git pode verificar as mudanças preparadas e bloquear o commit quando o CodeMender encontra uma vulnerabilidade com gravidade CRITICAL ou HIGH. Os desenvolvedores podem pular o hook. Portanto, use-o além da verificação na CI, não em vez dela.

Cada desenvolvedor que usa o hook precisa do seguinte:

  • A CLI do CodeMender, instalada e configurada conforme descrito em Instalar e configurar a CLI, incluindo gcloud auth application-default login e cm init. O hook precisa de cm no PATH.
  • O papel de usuário da Agent Platform (roles/aiplatform.user) em um projeto com acesso ao CodeMender. O CodeMender usa o projeto na variável de ambiente GOOGLE_CLOUD_PROJECT. Se essa variável não estiver definida, o CodeMender usará o projeto das suas Application Default Credentials ou o projeto padrão da CLI gcloud.

Para adicionar o hook, salve o script a seguir como .git/hooks/pre-commit no seu repositório:

#!/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

Torne o script executável e adicione .cm_project ao arquivo .gitignore para não confirmar o arquivo criado pelo CodeMender para rastrear o repositório:

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

Quando você executa git commit, o hook verifica os arquivos com mudanças preparadas. A verificação pode levar alguns minutos. O hook não desativa o sandbox do CodeMender.

Para fazer commit sem a verificação, execute git commit --no-verify.

Flags de verificação

As flags cm find a seguir controlam as verificações de solicitação de envio. Para todas as flags, execute cm find --help:

Sinalização padrão Descrição
--diff[=REF] Desativado Verifica as mudanças em comparação com REF, como origin/main. Sem REF, verifica mudanças não confirmadas em arquivos rastreados (em comparação com HEAD). Não pode ser usado com --deep.
--staged Desativado Com --diff, verifica apenas as mudanças preparadas.
--diff-depth DEPTH 1 Profundidade de travessia para análise de impacto (1 a 3, padrão: 1-hop).
--diff-workers COUNT 4 O número de arquivos a serem verificados ao mesmo tempo, de 1 a 16.
--diff-max-neighbors COUNT 10 O número máximo de arquivos dependentes a serem verificados.
--fail-on SEVERITIES CRITICAL,HIGH Com --diff, as gravidades que fazem cm find sair com o status 1. Com um valor vazio, as descobertas não afetam o status de saída.
--fail-on-truncation Desativado Com --diff, sai com o status 1 se o CodeMender encontrar mais arquivos dependentes do que o permitido por --diff-max-neighbors.
--format FORMAT table O formato do relatório: table, json ou sarif.
--output FILE Saída padrão O arquivo em que o relatório será gravado.

Solução de problemas

Esta seção descreve como resolver problemas comuns ao executar o CodeMender em pipelines de CI/CD.

Permissão negada

O registro mostra uma linha como esta:

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

A mensagem também pode incluir Permission 'aiplatform.interactions.create' denied. Verifique se:

  • O projeto tem acesso ao CodeMender.
  • A conta de serviço ou o usuário tem o papel de usuário da Agent Platform (roles/aiplatform.user) no projeto.
  • A API Agent Platform está ativada no projeto.
  • O CodeMender usa o projeto certo. No GitHub Actions, verifique o segredo GCP_PROJECT_ID. O Cloud Build usa o projeto que executa o build. Localmente, verifique a variável de ambiente GOOGLE_CLOUD_PROJECT ou seu projeto padrão se a variável não estiver definida.

Configuração de recursos em andamento

Se o registro mostrar Resource setup has just started. Please try again shortly. ou Resource setup is in progress. Please try again shortly., o CodeMender estará configurando recursos para seu projeto, o que geralmente leva alguns minutos. Execute o job novamente mais tarde.

Flag desconhecida: --diff

Se cm find falhar com Error: unknown flag: --diff, sua versão da CLI não vai oferecer suporte a verificações de solicitação de envio. Execute cm update ou faça o download da versão mais recente.

Branch de base não encontrada

Se cm find falhar com um erro como este, a ramificação de base não estará no checkout:

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

Busque a ramificação de base e o histórico dela antes de executar cm find. No GitHub Actions, defina fetch-depth: 0 em actions/checkout.

Arquivos não verificados

Uma linha com ❌, como [1/1] ❌ src/app.py: start session failed, significa que o CodeMender não conseguiu verificar esse arquivo. Verifique o erro na linha e execute o job de novo.

Nenhuma solicitação de envio de correção

Se o fluxo de trabalho não abrir uma solicitação de envio de correção, verifique o seguinte:

  • Se o job de correção automática falhar ao criar a solicitação de envio, ative a opção Permitir que as ações do GitHub criem e aprovem solicitações de pull. Para mais informações, consulte Configurar as definições do repositório.
  • Se o trabalho de correção automática for concluído sem abrir uma solicitação de envio, o CodeMender não corrigiu nenhuma descoberta. O registro do job mostra um aviso para cada descoberta que o CodeMender não corrigiu.

Falha no upload da verificação de código

Se a etapa de upload falhar com GitHub Code Security or GitHub Advanced Security must be enabled for this repository to use code scanning, ative a segurança de código do GitHub para o repositório ou exclua a etapa de upload. Para mais informações, consulte Configurar as definições do repositório.

Alerta não confirmado

Se cm falhar com warning not acknowledged. Please run interactively once to acknowledge or pass --bypass-warning, o CodeMender precisará de confirmação de que não pode pedir em um ambiente não interativo. Adicione --bypass-warning ao comando. Antes de fazer isso, leia os termos da prévia na parte de cima desta página.

Para receber mais ajuda, entre em contato com sua equipe de vendas.