Comment utiliser Bencher dans GitHub Actions


on:
  push:
    branches: main

jobs:
  benchmark_with_bencher:
    name: Continuous Benchmarking with Bencher
    runs-on: ubuntu-latest
    env:
      BENCHER_PROJECT: save-walter-white
      BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }}
      BENCHER_TESTBED: ubuntu-latest
      BENCHER_ADAPTER: json
    steps:
      - uses: actions/checkout@v3
      - uses: bencherdev/bencher@main
      - name: Track Benchmarks with Bencher
        run: |
          bencher run \
          --branch main \
          --err \
          "bencher mock"
  1. Créez un fichier workflow pour GitHub Actions. (ex: .github/workflows/benchmark.yml)
  2. ExĂ©cutez sur les Ă©vĂ©nements push vers la branche main. Consultez la documentation on de GitHub Actions pour une vue d’ensemble complĂšte. Voir aussi Pull Requests ci-dessous.
  3. Créez un job pour GitHub Actions. (ex: benchmark_with_bencher)
  4. Le Projet doit dĂ©jĂ  exister. DĂ©finissez le drapeau --project ou la variable d’environnement BENCHER_PROJECT avec le slug ou l’UUID du Projet (ex: BENCHER_PROJECT: save-walter-white).
  5. Le jeton API doit dĂ©jĂ  exister. Ajoutez BENCHER_API_TOKEN en tant que secret Repository. (ex: Repo -> Settings -> Secrets and variables -> Actions -> New repository secret). DĂ©finissez le drapeau --tokenou la variable d’environnement BENCHER_API_TOKEN avec le jeton API. (ex: BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }})
  6. Optionnel : rĂ©glez le drapeau --testbed ou la variable d’environnement BENCHER_TESTBED amenant au slug ou Ă  l’UUID de Testbed. (ex: BENCHER_TESTBED: ubuntu-latest) Le Testbed doit dĂ©jĂ  exister. Si ce n’est pas dĂ©fini, le Testbed localhost sera utilisĂ©.
  7. Optionnel : rĂ©glez le drapeau --adapter ou la variable d’environnement BENCHER_ADAPTER avec le nom de l’adaptateur dĂ©sirĂ©. (ex: BENCHER_ADAPTER: json) Si ce n’est pas dĂ©fini, l’Adaptateur magic sera utilisĂ©. Consultez les adaptateurs de harnais de benchmark pour une vue d’ensemble complĂšte.
  8. Extraites votre code source. (ex: uses: actions/checkout@v3)
  9. Installez le CLI de Bencher en utilisant GitHub Action. (ex: uses: bencherdev/bencher@main)
  10. Suivez vos benchmarks avec la sous-commande CLI bencher run:
    1. Optionnel : rĂ©glez le drapeau --branch ou la variable d’environnement BENCHER_BRANCH avec le slug ou l’UUID de la Branche. (ex: --branch main). La Branche doit dĂ©jĂ  exister. Si ce n’est pas dĂ©fini, la branche main sera utilisĂ©e.
    2. ParamĂ©trez la commande pour Ă©chouer si une Alerte est gĂ©nĂ©rĂ©e. (ex: --err) Pour qu’une Alerte soit gĂ©nĂ©rĂ©e, un Seuil doit dĂ©jĂ  exister.
    3. Exécutez vos benchmarks et générez un Account à partir des résultats. (ex: "bencher mock")

Pull Requests

Pour dĂ©tecter la rĂ©gression de performance dans les Pull Requests, vous devrez exĂ©cuter vos benchmarks sur les PRs. Si vous prĂ©voyez uniquement d’avoir des PRs provenant de branches au sein du mĂȘme dĂ©pĂŽt, vous pouvez simplement modifier l’exemple ci-dessus pour Ă©galement exĂ©cuter on sur les Ă©vĂ©nements pull_request.

⚠ Cette solution ne fonctionne que si toutes les PRs proviennent du mĂȘme dĂ©pĂŽt! Voir Pull Requests Ă  partir de Forks ci-dessous.

on:
  push:
    branches: main
  pull_request:

jobs:
  benchmark_with_bencher:
    name: Continuous Benchmarking with Bencher
    runs-on: ubuntu-latest
    env:
      BENCHER_PROJECT: save-walter-white
      BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }}
      BENCHER_TESTBED: ubuntu-latest
      BENCHER_ADAPTER: json
    steps:
      - uses: actions/checkout@v3
      - uses: bencherdev/bencher@main
      - name: Track Benchmarks with Bencher
        run: |
          bencher run \
          --if-branch "$GITHUB_REF_NAME" \
          --else-if-branch "$GITHUB_BASE_REF" \
          --else-if-branch main \
          --github-actions ${{ secrets.GITHUB_TOKEN }} \
          --err \
          "bencher mock"
  1. ExĂ©cutez sur les Ă©vĂ©nements push Ă  la branche main et sur les Ă©vĂ©nements pull_request. Il est important de limiter l’exĂ©cution on push uniquement Ă  certaines branches selectionnĂ©es (ex: main) pour empĂȘcher les pushes vers les branches de PR de s’exĂ©cuter deux fois!
  2. Au lieu d’utiliser toujours la branche main, utilisez les variables d’environnement par dĂ©faut de GitHub Action pour :
    1. Utiliser des données de branche actuelles si elles existent déjà. (ex: --if-branch "$GITHUB_REF_NAME")
    2. Créer un clone des données et des seuils de la branche cible de la PR si cela existe déjà. (ex: --else-if-branch "$GITHUB_BASE_REF")
    3. Sinon, créez un clone des données et des seuils de la branche main. (ex: --else-if-branch main)
    4. Il existe plusieurs options pour dĂ©finir la branche du projet. Voir la sĂ©lection de branche pour une vue d’ensemble complĂšte.
  3. ParamĂ©trez le jeton d’authentification de l’API GitHub. (ex: --github-actions ${{ secrets.GITHUB_TOKEN }}). Lorsque cette option est dĂ©finie dans le cadre d’une pull request, alors les rĂ©sultats seront ajoutĂ©s Ă  la pull request sous forme de commentaire. Ceci utilise la variable d’environnement GITHUB_TOKEN des GitHub Actions.
  4. Consultez la documentation bencher run pour une vue d’ensemble complùte de toutes les façons de configurer le commentaire de pull request avec les drapeaux --ci-*.

Pull Requests Ă  partir de Forks

Si vous prĂ©voyez d’accepter les pull requests Ă  partir de forks, comme c’est souvent le cas dans les projets open source publics, alors vous devrez gĂ©rer les choses un peu diffĂ©remment. Pour des raisons de sĂ©curitĂ©, les secrets tels que votre BENCHER_API_TOKEN et le GITHUB_TOKEN ne sont pas disponibles dans GitHub Actions pour les PRs de fork. C’est-Ă -dire que si un contributeur externe ouvre une PR Ă  partir d’un fork, l’exemple ci-dessus ne fonctionnera pas. Il y a trois options pour les PRs de fork :

Tester la PR de Fork Ă  partir de la Branche Cible

on:
  push:
    branches: main
  pull_request_target:

jobs:
  benchmark_main_with_bencher:
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    name: Benchmark main with Bencher
    runs-on: ubuntu-latest
    env:
      BENCHER_PROJECT: save-walter-white
      BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }}
      BENCHER_TESTBED: ubuntu-latest
      BENCHER_ADAPTER: json
    steps:
      - uses: actions/checkout@v3
      - uses: bencherdev/bencher@main
      - name: Track Benchmarks with Bencher
        run: |
          bencher run \
          --branch main \
          --err \
          "bencher mock"

  benchmark_pr_with_bencher:
    if: github.event_name == 'pull_request_target'
    name: Benchmark PR with Bencher
    runs-on: ubuntu-latest
    env:
      BENCHER_PROJECT: save-walter-white
      BENCHER_ADAPTER: json
      BENCHER_TESTBED: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          repository: ${{ github.event.pull_request.head.repo.full_name }}
          persist-credentials: false
      - uses: bencherdev/bencher@main
      - name: Track Benchmarks with Bencher
        run: |
          bencher run \
          --if-branch "${{ github.event.pull_request.head.ref }}" \
          --else-if-branch "${{ github.event.pull_request.base.ref }}" \
          --else-if-branch main \
          --github-actions "${{ secrets.GITHUB_TOKEN }}" \
          --token "${{ secrets.BENCHER_API_TOKEN }}" \
          --err \
          "bencher mock"
  1. Exécutez sur les événements push à la branche main et sur les événements pull_request_target.
  2. CrĂ©ez un job qui s’exĂ©cute uniquement pour les Ă©vĂ©nements push Ă  la branche main. À part la condition if, ce job est presque identique Ă  l’exemple original ci-dessus.
  3. CrĂ©ez un job qui s’exĂ©cute uniquement pour les Ă©vĂ©nements pull_request_target.
    1. Extraites la branche de pull request.
    2. Transmettez directement tous les secrets. Utilisez --token ${{ secrets.BENCHER_API_TOKEN }} au lieu de la variable d’environnement BENCHER_API_TOKEN.
    3. Exécutez et suivez vos benchmarks de pull request avec bencher run.

Cette configuration fonctionne parce que pull_request_target s’exĂ©cute dans le contexte de la branche cible de la pull request, oĂč les secrets tels que votre BENCHER_API_TOKEN et le GITHUB_TOKEN sont disponibles. Par consĂ©quent, ce workflow ne s’exĂ©cutera que s’il existe sur la branche cible. Évitez de dĂ©finir des secrets comme des variables d’environnement, comme BENCHER_API_TOKEN. Au lieu de cela, passez explicitement le jeton API Ă  bencher run. (ex: --token ${{ secrets.BENCHER_API_TOKEN }}) Voir ce document du GitHub Security Lab et cet article de blog sur la prĂ©vention des requĂȘtes pwn pour une vue d’ensemble complĂšte.

Tester la PR de Fork à partir de la Branche Cible avec Réviseurs Nécessaires

on:
  push:
    branches: main
  pull_request_target:

jobs:
  benchmark_main_with_bencher:
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    name: Benchmark main with Bencher
    runs-on: ubuntu-latest
    env:
      BENCHER_PROJECT: save-walter-white
      BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }}
      BENCHER_TESTBED: ubuntu-latest
      BENCHER_ADAPTER: json
    steps:
      - uses: actions/checkout@v3
      - uses: bencherdev/bencher@main
      - name: Track Benchmarks with Bencher
        run: |
          bencher run \
          --branch main \
          --err \
          "bencher mock"

  benchmark_pr_requires_review:
    if: github.event_name == 'pull_request_target'
    environment:
      ${{ (github.event.pull_request.head.repo.full_name == github.repository && 'internal') || 'external' }}
    runs-on: ubuntu-latest
    steps:
      - run: true

  benchmark_pr_with_bencher:
    needs: benchmark_pr_requires_review
    name: Benchmark PR with Bencher
    runs-on: ubuntu-latest
    env:
      BENCHER_PROJECT: save-walter-white
      BENCHER_ADAPTER: json
      BENCHER_TESTBED: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          repository: ${{ github.event.pull_request.head.repo.full_name }}
          persist-credentials: false
      - uses: bencherdev/bencher@main
      - name: Track Benchmarks with Bencher
        run: |
          bencher run \
          --if-branch "${{ github.event.pull_request.head.ref }}" \
          --else-if-branch "${{ github.event.pull_request.base.ref }}" \
          --else-if-branch main \
          --github-actions "${{ secrets.GITHUB_TOKEN }}" \
          --token "${{ secrets.BENCHER_API_TOKEN }}" \
          --err \
          "bencher mock"

Cette configuration est exactement la mĂȘme que Tester la PR de Fork Ă  partir de la Branche Cible avec l’exigence supplĂ©mentaire de l’approbation d’un RĂ©viseur NĂ©cessaire avant chaque exĂ©cution de pull request de fork. Les pull requests du mĂȘme dĂ©pĂŽt ne nĂ©cessitent pas d’approbation. Pour configurer cela, vous devez crĂ©er deux Environnements d’Action GitHub (ex: Repo -> Settings -> Environments -> New environment). L’environnement internal ne doit avoir aucune RĂšgles de protection de dĂ©ploiement. Cependant, l’environnement external doit avoir des RĂ©viseurs nĂ©cessaires dĂ©finis comme ceux de confiance pour rĂ©viser les PRs de fork avant le benchmarking.

Tester la PR de Fork et Télécharger à partir de la Branche par Défaut

name: Run and Cache Benchmarks

on: pull_request

jobs:
  benchmark:
    name: Run Benchmarks
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Mock Benchmark
        run: echo '{"bencher::mock_0": { "latency": { "value": 1.0 }}}' &> benchmark_results.txt
      - uses: actions/upload-artifact@v3
        with:
          name: benchmark_results.txt
          path: ./benchmark_results.txt
      - uses: actions/upload-artifact@v3
        with:
          name: pr_event.json
          path: ${{ env.GITHUB_EVENT_PATH }}
name: Track Benchmarks

on:
  workflow_run:
    workflows: [Run and Cache Benchmarks]
    types:
      - completed

jobs:
  track_with_bencher:
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    runs-on: ubuntu-latest
    env:
      BENCHER_PROJECT: save-walter-white
      BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }}
      BENCHER_ADAPTER: json
      BENCHER_TESTBED: ubuntu-latest
      BENCHMARK_RESULTS: benchmark_results.txt
      PR_EVENT: pr_event.json
    steps:
      - name: Download Benchmark Results
        uses: actions/github-script@v6
        with:
          script: |
            function downloadArtifact(artifactName) {
              let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
                owner: context.repo.owner,
                repo: context.repo.repo,
                run_id: context.payload.workflow_run.id,
              });
              let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
                return artifact.name == artifactName
              })[0];
              if (!matchArtifact) {
                core.setFailed(`Failed to find artifact: ${artifactName}`);
              }
              let download = await github.rest.actions.downloadArtifact({
                owner: context.repo.owner,
                repo: context.repo.repo,
                artifact_id: matchArtifact.id,
                archive_format: 'zip',
              });
              let fs = require('fs');
              fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/${artifactName}.zip`, Buffer.from(download.data));
            }
            downloadArtifact(process.env.BENCHMARK_RESULTS);
            downloadArtifact(process.env.PR_EVENT);
      - name: Unzip Benchmark Results
        run: |
          unzip $BENCHMARK_RESULTS.zip
          unzip $PR_EVENT.zip
      - name: Export PR Context
        uses: actions/github-script@v6
        with:
          script: |
            let fs = require('fs');
            let prEvent = JSON.parse(fs.readFileSync(process.env.PR_EVENT, {encoding: 'utf8'}));
            fs.appendFileSync(process.env.GITHUB_ENV, `PR_NUMBER=${prEvent.number}`);
            fs.appendFileSync(process.env.GITHUB_ENV, `PR_HEAD=${prEvent.pull_request.head.ref}`);
            fs.appendFileSync(process.env.GITHUB_ENV, `PR_BASE=${prEvent.pull_request.base.ref}`);
      - uses: bencherdev/bencher@main
          - name: Track Benchmarks with Bencher
            run: |
              bencher run \
              --if-branch "${{ env.PR_HEAD }}" \
              --else-if-branch "${{ env.PR_BASE }}" \
              --else-if-branch main \
              --github-actions "${{ secrets.GITHUB_TOKEN }}" \
              --ci-number "${{ env.PR_NUMBER }}" \
              --err \
              --file $BENCHMARK_RESULTS
  1. Créez un fichier de workflow Exécutez et Cachez les Benchmarks.
  2. Exécutez vos benchmarks sur les événements pull_request.
  3. Sauvegardez les résultats des benchmarks dans un fichier et téléchargez-les comme un artefact.
  4. TĂ©lĂ©chargez l’évĂ©nement pull_request comme un artefact.
  5. Créez un second fichier de workflow, Suivez les Benchmarks.
  6. EnchaĂźnez Suivez les Benchmarks Ă  ExĂ©cutez et Cachez les Benchmarks avec l’évĂ©nement workflow_run.
  7. Extrayez les donnĂ©es nĂ©cessaires de l’évĂ©nement pull_request en cache.
  8. Suivez les résultats de benchmark en cache avec bencher run.
  9. CrĂ©ez un troisiĂšme fichier de workflow et utilisez l’exemple initial ci-dessus pour exĂ©cuter sur les Ă©vĂ©nements push Ă  la branche main.

Cette configuration fonctionne parce que workflow_run s’exĂ©cute dans le contexte de la branche par dĂ©faut du dĂ©pĂŽt, oĂč les secrets tels que votre BENCHER_API_TOKEN et le GITHUB_TOKEN sont disponibles. Par consĂ©quent, ces workflows ne s’exĂ©cuteront que s’ils existent sur la branche par dĂ©faut. Voir l’utilisation de donnĂ©es provenant du workflow dĂ©clencheur pour une vue d’ensemble complĂšte. Le numĂ©ro de pull request, la branche de tĂȘte et la branche de base utilisĂ©s dans le workflow initial doivent ĂȘtre explicitement transmis car ils ne sont pas disponibles Ă  l’intĂ©rieur de workflow_run.



🐰 FĂ©licitations ! Vous avez appris Ă  utiliser Bencher dans GitHub Actions ! 🎉


Continuez : Vue d’ensemble du Benchmarking ➡

đŸ€– Ce document a Ă©tĂ© automatiquement gĂ©nĂ©rĂ© par OpenAI GPT-4. Il peut ne pas ĂȘtre prĂ©cis et peut contenir des erreurs. Si vous trouvez des erreurs, veuillez ouvrir une issue sur GitHub.