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"
- Créez un fichier
workflow
pour GitHub Actions. (ex:.github/workflows/benchmark.yml
) - Exécutez sur les événements
push
vers la branchemain
. Consultez la documentationon
de GitHub Actions pour une vue dâensemble complĂšte. Voir aussi Pull Requests ci-dessous. - CrĂ©ez un
job
pour GitHub Actions. (ex:benchmark_with_bencher
) - Le Projet doit déjà exister. Définissez le drapeau
--project
ou la variable dâenvironnementBENCHER_PROJECT
avec le slug ou lâUUID du Projet (ex:BENCHER_PROJECT: save-walter-white
). - 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--token
ou la variable dâenvironnementBENCHER_API_TOKEN
avec le jeton API. (ex:BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }}
) - Optionnel : réglez le drapeau
--testbed
ou la variable dâenvironnementBENCHER_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 Testbedlocalhost
sera utilisé. - Optionnel : réglez le drapeau
--adapter
ou la variable dâenvironnementBENCHER_ADAPTER
avec le nom de lâadaptateur dĂ©sirĂ©. (ex:BENCHER_ADAPTER: json
) Si ce nâest pas dĂ©fini, lâAdaptateurmagic
sera utilisĂ©. Consultez les adaptateurs de harnais de benchmark pour une vue dâensemble complĂšte. - Extraites votre code source. (ex:
uses: actions/checkout@v3
) - Installez le CLI de Bencher en utilisant GitHub Action. (ex:
uses: bencherdev/bencher@main
) - Suivez vos benchmarks avec la sous-commande CLI
bencher run
:- Optionnel : réglez le drapeau
--branch
ou la variable dâenvironnementBENCHER_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 branchemain
sera utilisée. - 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. - ExĂ©cutez vos benchmarks et gĂ©nĂ©rez un Account Ă partir des rĂ©sultats. (ex:
"bencher mock"
)
- Optionnel : réglez le drapeau
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"
- Exécutez sur les événements
push
Ă la branchemain
et sur les événementspull_request
. Il est important de limiter lâexĂ©cutionon
push
uniquement à certaines branches selectionnées (ex:main
) pour empĂȘcher les pushes vers les branches de PR de sâexĂ©cuter deux fois! - Au lieu dâutiliser toujours la branche
main
, utilisez les variables dâenvironnement par dĂ©faut de GitHub Action pour :- Utiliser des donnĂ©es de branche actuelles si elles existent dĂ©jĂ . (ex:
--if-branch "$GITHUB_REF_NAME"
) - 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"
) - Sinon, créez un clone des données et des seuils de la branche
main
. (ex:--else-if-branch main
) - Il existe plusieurs options pour dĂ©finir la branche du projet. Voir la sĂ©lection de branche pour une vue dâensemble complĂšte.
- Utiliser des données de branche actuelles si elles existent déjà . (ex:
- 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âenvironnementGITHUB_TOKEN
des GitHub Actions. - 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
- Tester la PR de Fork à partir de la Branche Cible avec Réviseurs Nécessaires
- Tester la PR de Fork et Télécharger à partir de la Branche par Défaut
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"
- Exécutez sur les événements
push
Ă la branchemain
et sur les événementspull_request_target
. - Créez un
job
qui sâexĂ©cute uniquement pour les Ă©vĂ©nementspush
Ă la branchemain
. Ă part la conditionif
, ce job est presque identique Ă lâexemple original ci-dessus. - CrĂ©ez un
job
qui sâexĂ©cute uniquement pour les Ă©vĂ©nementspull_request_target
.- Extraites la branche de pull request.
- Transmettez directement tous les secrets. Utilisez
--token ${{ secrets.BENCHER_API_TOKEN }}
au lieu de la variable dâenvironnementBENCHER_API_TOKEN
. - 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
- Créez un fichier de workflow
Exécutez et Cachez les Benchmarks
. - Exécutez vos benchmarks sur les événements
pull_request
. - Sauvegardez les résultats des benchmarks dans un fichier et téléchargez-les comme un artefact.
- TĂ©lĂ©chargez lâĂ©vĂ©nement
pull_request
comme un artefact. - Créez un second fichier de workflow,
Suivez les Benchmarks
. - EnchaĂźnez
Suivez les Benchmarks
ĂExĂ©cutez et Cachez les Benchmarks
avec lâĂ©vĂ©nementworkflow_run
. - Extrayez les donnĂ©es nĂ©cessaires de lâĂ©vĂ©nement
pull_request
en cache. - Suivez les résultats de benchmark en cache avec
bencher run
. - CrĂ©ez un troisiĂšme fichier de workflow et utilisez lâexemple initial ci-dessus pour exĂ©cuter sur les Ă©vĂ©nements
push
Ă la branchemain
.
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 ! đ