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_TESTBED: ubuntu-latest
BENCHER_ADAPTER: json
steps:
- uses: actions/checkout@v4
- uses: bencherdev/bencher@main
- name: Track Benchmarks with Bencher
run: |
bencher run \
--branch "$GITHUB_REF_NAME" \
--token "${{ secrets.BENCHER_API_TOKEN }}" \
--err \
"bencher mock"
  1. Créez un fichier workflow GitHub Actions. (ex: .github/workflows/benchmarks.yml)
  2. ExĂ©cutez lors d’évĂ©nements push vers la branche main. RĂ©fĂ©rez-vous Ă  la documentation GitHub Actions on pour un aperçu complet. Voir aussi Demandes de fusion ci-dessous.
  3. Créez une job GitHub Actions. (ex: benchmark_with_bencher)
  4. Le projet doit dĂ©jĂ  exister. DĂ©finissez l’option --project ou la variable d’environnement BENCHER_PROJECT pour l’identifiant court ou l’UUID du projet (ex: BENCHER_PROJECT: save-walter-white).
  5. Facultatif: Utilisez l’option --testbed ou la variable d’environnement BENCHER_TESTBED pour l’identifiant court ou l’UUID du banc de test. (ex: BENCHER_TESTBED: ubuntu-latest) Le banc de test doit dĂ©jĂ  exister. Si cela n’est pas dĂ©fini, alors le banc de test localhost sera utilisĂ©.
  6. Facultatif: DĂ©finissez l’option --adapter ou la variable d’environnement BENCHER_ADAPTER pour le nom de l’adaptateur dĂ©sirĂ©. (ex: BENCHER_ADAPTER: json) Si cela n’est pas dĂ©fini, alors l’adaptateur magic sera utilisĂ©. Voir adaptateurs de banc de test pour un aperçu complet.
  7. Enregistrez votre code source. (ex: uses: actions/checkout@v4)
  8. Installez le CLI Bencher à l’aide du GitHub Action. (ex: uses: bencherdev/bencher@main)
  9. Suivez vos benchmarks avec la sous-commande CLI bencher run:
    1. Facultatif: DĂ©finissez l’option --branch ou la variable d’environnement BENCHER_BRANCH pour l’identifiant court ou l’UUID de la branche. (ex: --branch main) La branche doit dĂ©jĂ  exister. Si cela n’est pas dĂ©fini, alors la branche main sera utilisĂ©e.
    2. Le token d’API doit dĂ©jĂ  exister. Ajoutez BENCHER_API_TOKEN en tant que secret de dĂ©pĂŽt. (ex: DĂ©pĂŽt -> Settings -> Secrets and variables -> Actions -> New repository secret) DĂ©finissez l’option --token ou la variable d’environnement BENCHER_API_TOKEN pour le token d’API. (ex: --token ${{ secrets.BENCHER_API_TOKEN }})
    3. Configurez 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.
    4. Exécutez vos benchmarks et générez un rapport à partir des résultats. (ex: "bencher mock")

Demandes de Fusion

Pour identifier les rĂ©gressions de performance dans les demandes de fusion (Pull Requests), vous devez exĂ©cuter vos benchmarks sur ces demandes. Si vous ne vous attendez qu’à n’avoir des demandes de fusion que provenant de branches se trouvent dans le mĂȘme dĂ©pĂŽt, vous pouvez simplement modifier l’exemple ci-dessus pour exĂ©cuter Ă©galement on lors d’évĂ©nements pull_request.

⚠ Cette solution fonctionne uniquement si toutes les demandes de fusion sont issues du mĂȘme dĂ©pĂŽt! Voir Demandes de fusion Ă  partir de Forks ci-dessous.

on:
pull_request:
types: [opened, reopened, synchronize]
jobs:
benchmark_pr_with_bencher:
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
permissions:
pull-requests: write
name: Continuous Benchmarking with Bencher
runs-on: ubuntu-latest
env:
BENCHER_PROJECT: save-walter-white
BENCHER_TESTBED: ubuntu-latest
BENCHER_ADAPTER: json
steps:
- uses: actions/checkout@v4
- 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 }}" \
--token "${{ secrets.BENCHER_API_TOKEN }}" \
--err \
"bencher mock"
  1. Créez un fichier workflow pour GitHub Actions. (ex : .github/workflows/pr_benchmarks.yml)
  2. ExĂ©cutez lors des Ă©vĂ©nements pull_request si et seulement si la pull request provient du mĂȘme dĂ©pĂŽt. Pour gĂ©rer les Pull Requests depuis des Forks, voir Pull Requests de Forks ci-dessous.
  3. DĂ©finissez les permissions pour le GITHUB_TOKEN sur write pour les pull-requests. Selon vos paramĂštres GitHub, cela peut ne pas ĂȘtre nĂ©cessaire. Cependant, pour toutes les organisations et les dĂ©pĂŽts personnels crĂ©Ă©s aprĂšs le 02 fĂ©vrier 2023, c’est le comportement par dĂ©faut. Consultez la documentation GitHub pour un aperçu complet.
  4. SĂ©lectionnez la branche Ă  utiliser :
    1. Utilisez les données de branche actuelle si elles existent déjà. (ex : --if-branch "$GITHUB_REF_NAME")
    2. CrĂ©ez un clone des donnĂ©es et des seuils de la branche cible de la PR s’ils existent 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)
  5. DĂ©finissez 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, les rĂ©sultats seront ajoutĂ©s Ă  la pull request sous forme de commentaire. Cela utilise la variable d’environnement GITHUB_TOKEN des GitHub Actions.
  6. Consultez la documentation bencher run pour un aperçu complet de toutes les façons de configurer le commentaire de la pull request avec les drapeaux --ci-*.
  7. (Non montrĂ©) CrĂ©ez un second fichier workflow pour les GitHub Actions et utilisez l’exemple initial ci-dessus pour exĂ©cuter lors des Ă©vĂ©nements push vers la branche main. (ex : .github/workflows/benchmarks.yml)

Demandes de Fusion Ă  partir de Forks

Si vous prĂ©voyez d’accepter des demandes de fusion provenant de forks, comme cela 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Ă©, des secrets tels que votre BENCHER_API_TOKEN et le GITHUB_TOKEN ne sont pas disponibles dans GitHub Actions pour les demandes de fusion de forks. C’est-Ă -dire que si un contributeur externe ouvre une demande de fusion Ă  partir d’un fork, l’exemple ci-dessus ne fonctionnera pas. Il existe deux options pour les demandes de fusion provenant de forks :

Evaluer la demande de fusion Ă  partir de la branche cible avec des examinateurs requis

⚠ Il est trĂšs, trĂšs important d’examiner minutieusement toute PR de bifurcation avant de l’approuver! Si vous ne le faites pas, cela pourrait entraĂźner une demande de pwn !

Si vous préférez ne pas avoir cela sur la conscience, voir Benchmark de PR de bifurcation et Upload à partir de la branche par défaut ci-dessous.

on:
pull_request_target:
types: [opened, reopened, synchronize]
jobs:
fork_pr_requires_review:
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: fork_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@v4
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.number }}/merge' \
--else-if-branch '${{ github.base_ref }}' \
--else-if-branch main \
--github-actions "${{ secrets.GITHUB_TOKEN }}" \
--token "${{ secrets.BENCHER_API_TOKEN }}" \
--err \
"bencher mock"
  1. Créez un fichier workflow GitHub Actions. (ex: .github/workflows/pr_benchmarks.yml)
  2. Exécutez des événements pull_request_target.
  3. CrĂ©ez une job nommĂ©e fork_pr_requires_review qui nĂ©cessite l’approbation d’un examinateur requis avant chaque exĂ©cution de demande de fusion de fork (external).
  4. Créez une troisiÚme job qui dépend de fork_pr_requires_review.
    1. Enregistrez la branche de la demande de fusion mais ne conservez pas les identifiants git. (ex: persist-credentials: false)
    2. Utilisez des guillemets simples autour de toutes les entrées non fiables. (ex: --if-branch '${{ github.head_ref }}')
    3. Passez tous les secrets directement. (ex: --token "${{ secrets.BENCHER_API_TOKEN }}")
    4. Exécutez et suivez vos benchmarks de demandes de fusion avec bencher run.
  5. (Non montrĂ©) CrĂ©ez un deuxiĂšme fichier workflow GitHub Actions et utilisez l’exemple initial ci-dessus pour exĂ©cuter lors d’évĂ©nements push vers la branche main. (ex: .github/workflows/benchmarks.yml)

Cet arrangement fonctionne parce que pull_request_target s’exĂ©cute dans le contexte de la branche cible de la demande de fusion, oĂč des secrets tels que votre BENCHER_API_TOKEN et le GITHUB_TOKEN sont disponibles. Par consĂ©quent, ce workflow s’exĂ©cutera uniquement s’il existe sur la branche cible.

Pour configurer cela, vous devez crĂ©er deux Environnements d’Action GitHub (ex: DĂ©pĂŽt -> Settings -> Environments -> New environment). L’environnement internal ne doit pas avoir de RĂšgles de protection du dĂ©ploiement. Cependant, l’environnement external doit avoir des Examinateurs requis dĂ©finis pour ceux de confiance pour examiner les demandes de fusion de fork avant le benchmarking.

Il est trĂšs important d’entourer le nom de la branche de la demande de fusion (rĂ©fĂ©rence de tĂȘte) de guillemets simples. (ex: --if-branch '${{ github.head_ref }}') Sinon, un attaquant pourrait crĂ©er une branche malicieusement nommĂ©e qui effectue une injection de commandes. Voir cette Ă©tude du GitHub Security Lab sur la prĂ©vention des requĂȘtes malveillantes provenant d’entrĂ©es non fiables pour un aperçu complet.

Évitez de dĂ©finir des secrets en tant que variables d’environnement, tels que GITHUB_TOKEN et BENCHER_API_TOKEN. Passez plutĂŽt explicitement les secrets Ă  bencher run. (ex: --token "${{ secrets.BENCHER_API_TOKEN }}") Consultez cette Ă©tude du GitHub Security Lab et ce billet de blog sur la prĂ©vention des requĂȘtes malveillantes pour un aperçu complet.

Evaluer la demande de fusion et charger depuis la branche par défaut

name: Run and Cache Benchmarks
on:
pull_request:
types: [opened, reopened, synchronize]
jobs:
benchmark:
name: Run Benchmarks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Mock Benchmarking
run: |
/bin/echo '{ "bencher::mock_0": { "latency": { "value": 1.0 } } }' > benchmark_results.json
- name: Upload Benchmark Results
uses: actions/upload-artifact@v4
with:
name: benchmark_results.json
path: ./benchmark_results.json
- name: Upload GitHub Pull Request Event
uses: actions/upload-artifact@v4
with:
name: event.json
path: ${{ github.event_path }}
  1. Créez un fichier de workflow Run and Cache Benchmarks. (ex: .github/workflows/pr_benchmarks.yml)
  2. ExĂ©cutez tous les jobs du workflow lors d’évĂ©nements pull_request.
  3. Exécutez les benchmarks et enregistrez les résultats dans un fichier. (ex: benchmark_results.json)
  4. TĂ©lĂ©chargez le fichier de rĂ©sultats de benchmarks en tant qu’artefact.
  5. TĂ©lĂ©chargez l’objet d’évĂ©nement pull_request en tant qu’artefact.
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_ADAPTER: json
BENCHER_TESTBED: ubuntu-latest
BENCHMARK_RESULTS: benchmark_results.json
PR_EVENT: event.json
steps:
- name: Download Benchmark Results
uses: actions/github-script@v6
with:
script: |
async 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));
}
await downloadArtifact(process.env.BENCHMARK_RESULTS);
await downloadArtifact(process.env.PR_EVENT);
- name: Unzip Benchmark Results
run: |
unzip $BENCHMARK_RESULTS.zip
unzip $PR_EVENT.zip
- name: Export PR Event Data
uses: actions/github-script@v6
with:
script: |
let fs = require('fs');
let prEvent = JSON.parse(fs.readFileSync(process.env.PR_EVENT, {encoding: 'utf8'}));
core.exportVariable("PR_HEAD", `${prEvent.number}/merge`);
core.exportVariable("PR_BASE", prEvent.pull_request.base.ref);
core.exportVariable("PR_DEFAULT", prEvent.pull_request.base.repo.default_branch);
core.exportVariable("PR_NUMBER", prEvent.number);
- 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 '${{ env.PR_DEFAULT }}' \
--ci-number '${{ env.PR_NUMBER }}' \
--github-actions "${{ secrets.GITHUB_TOKEN }}" \
--token "${{ secrets.BENCHER_API_TOKEN }}" \
--err \
--file "$BENCHMARK_RESULTS"
  1. Créez un second fichier de workflow, Track Benchmarks. (ex: .github/workflows/track_benchmarks.yml)
  2. ChaĂźne Track Benchmarks Ă  Run and Cache Benchmarks avec l’évĂ©nement workflow_run.
  3. TĂ©lĂ©chargez les rĂ©sultats de benchmarks en cache et l’évĂ©nement pull_request.
  4. Extrayez les rĂ©sultats de benchmarks en cache et l’évĂ©nement pull_request.
  5. Exportez les donnĂ©es nĂ©cessaires de l’évĂ©nement pull_request en tant que variables d’environnement.
  6. Suivez les résultats de benchmarks en cache avec bencher run :
    1. Utilisez des guillemets simples autour de toutes les entrées non fiables. (ex: --if-branch '${{ env.PR_HEAD }}')
    2. Passez explicitement le numéro de la demande de fusion. (ex: --ci-number '${{ env.PR_NUMBER }}')
    3. Passez le chemin de fichier vers le fichier de résultats de benchmarks. (ex: --file "$BENCHMARK_RESULTS")
  7. (Non montrĂ©) CrĂ©ez un troisiĂšme fichier de workflow GitHub Actions et utilisez l’exemple initial ci-dessus pour exĂ©cuter lors d’évĂ©nements push vers la branche main. (ex: .github/workflows/benchmarks.yml)

Cet arrangement fonctionne parce que workflow_run s’exĂ©cute dans le contexte de la branche par dĂ©faut du dĂ©pĂŽt, oĂč des secrets tels que votre BENCHER_API_TOKEN et le GITHUB_TOKEN sont disponibles. Par consĂ©quent, ces workflows s’exĂ©cuteront uniquement s’ils existent sur la branche par dĂ©faut. Voir utiliser des donnĂ©es du workflow dĂ©clencheur pour un aperçu complet.

Il est trĂšs important d’entourer le nom de la branche de la demande de fusion (rĂ©fĂ©rence de tĂȘte) de guillemets simples. (ex: --if-branch '${{ env.PR_HEAD }}') Sinon, un attaquant pourrait crĂ©er une branche malicieusement nommĂ©e qui effectue une injection de commandes. Voir cette Ă©tude du GitHub Security Lab sur la prĂ©vention des requĂȘtes malveillantes provenant d’entrĂ©es non fiables pour un aperçu complet.

Évitez de dĂ©finir des secrets en tant que variables d’environnement dans le fichier de workflow Run and Cache Benchmarks. Consultez cette Ă©tude du GitHub Security Lab et ce billet de blog sur la prĂ©vention des requĂȘtes malveillantes pour un aperçu complet.



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


Continuer: Aperçu 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.