Wie Bencher in GitHub-Aktionen verwendet wird
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"
- Erstellen Sie eine GitHub Actions
workflow
Datei. (z.B.:.github/workflows/benchmark.yml
) - Führen Sie
push
Events zummain
Zweig durch. Siehe GitHub Actionson
Dokumentation für einen vollständigen Überblick. Siehe auch Pull Requests unten. - Erstellen Sie eine GitHub Actions
job
. (z.B.:benchmark_with_bencher
) - Das Projekt muss bereits existieren. Setzen Sie das
--project
Flag oder dieBENCHER_PROJECT
Umgebungsvariable auf den Projektslug oder UUID (z.B.:BENCHER_PROJECT: save-walter-white
). - Das API-Token muss bereits existieren. Fügen Sie
BENCHER_API_TOKEN
als Repository Geheimnis hinzu. (z.B.:Repo -> Einstellungen -> Geheimnisse und Variablen -> Aktionen -> Neues Repository-Geheimnis
) Setzen Sie das--token
Flag oder dieBENCHER_API_TOKEN
Umgebungsvariable auf das API-Token. (z.B.:BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }}
) - Optional: Setzen Sie das
--testbed
Flag oder dieBENCHER_TESTBED
Umgebungsvariable auf den Testbed Slug oder UUID. (z.B.:BENCHER_TESTBED: ubuntu-latest
) Das Testbed muss bereits existieren. Wird dies nicht gesetzt, wird daslocalhost
Testbed verwendet. - Optional: Setzen Sie das
--adapter
Flag oder dieBENCHER_ADAPTER
Umgebungsvariable auf den gewünschten Adapternamen. (z.B.:BENCHER_ADAPTER: json
) Wird dies nicht gesetzt, wird dermagic
Adapter verwendet. Siehe Benchmark Harness Adapter für einen vollständigen Überblick. - Checken Sie Ihren Quellcode aus. (z.B.:
uses: actions/checkout@v3
) - Installieren Sie die Bencher CLI mit der GitHub Action. (z.B.:
uses: bencherdev/bencher@main
) - Verfolgen Sie Ihre Benchmarks mit dem
bencher run
CLI-Unterbefehl:- Optional: Setzen Sie das
--branch
Flag oder dieBENCHER_BRANCH
Umgebungsvariable auf den Branch Slug oder UUID. (z.B.:--branch main
) Der Branch muss bereits existieren. Wird dies nicht gesetzt, wird dermain
Branch verwendet. - Setzen Sie den Befehl zum Fehlschlagen, wenn ein Alarm generiert wird. (z.B.:
--err
) Damit ein Alarm generiert wird, muss bereits ein Threshold existieren. - Führen Sie Ihre Benchmarks durch und erzeugen Sie einen Bericht aus den Ergebnissen. (z.B.:
"bencher mock"
)
- Optional: Setzen Sie das
Pull-Anfragen
Um eine Performance-Regression in Pull-Anfragen zu erkennen, müssen Sie Ihre Benchmarks bei den PRs durchführen.
Wenn Sie nur erwarten, dass Sie PRs von Zweigen innerhalb des gleichen Repositories haben, können Sie das oben stehende Beispiel einfach ändern, um auch bei pull_request
Events zu laufen.
⚠️ Diese Lösung funktioniert nur, wenn alle PRs aus dem gleichen Repository stammen! Siehe Pull-Anfragen von Forks unten.
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"
- Führen Sie
push
Events zummain
Zweig und aufpull_request
Events aus. Es ist wichtig, das Laufen beipush
nur auf die ausgewählten Zweige zu beschränken (z.B.:main
), um zu verhindern, dass Pushes zu PR-Zweigen doppelt ausgeführt werden! - Verwenden Sie statt dem
main
Zweig immer die standardmäßigen Umgebungsvariablen der GitHub-Aktion um:- Die aktuellen Branch-Daten zu verwenden, wenn sie bereits existieren. (z.B.:
--if-branch "$GITHUB_REF_NAME"
) - Erstellen Sie einen Klon der PR-Zielbranch-Daten und Schwellenwert, wenn sie bereits existieren. (z.B.:
--else-if-branch "$GITHUB_BASE_REF"
) - Ansonsten erstellen Sie einen Klon der
main
Branch-Daten und Schwellenwerte. (z.B.:--else-if-branch main
) - Es gibt mehrere Optionen für die Einstellung des Projektbranches. Siehe Branch Auswahl für einen vollständigen Überblick.
- Die aktuellen Branch-Daten zu verwenden, wenn sie bereits existieren. (z.B.:
- Setzen Sie das GitHub API Authentifizierungstoken. (z.B.:
--github-actions ${{ secrets.GITHUB_TOKEN }}
) Wenn diese Option als Teil einer Pull-Anfrage gesetzt ist, werden die Ergebnisse als Kommentar zur Pull-Anfrage hinzugefügt. Dies verwendet die GitHub ActionsGITHUB_TOKEN
Umgebungsvariable. - Siehe die bencher run Dokumentation für einen vollständigen Überblick über alle Möglichkeiten zur Konfiguration des Pull-Anfragen-Kommentars mit den
--ci-*
Flags.
Pull-Anfragen von Forks
Wenn Sie planen, Pull-Anfragen von Forks anzunehmen, wie es oft der Fall bei öffentlichen Open-Source-Projekten ist,
müssen Sie die Dinge ein wenig anders behandeln.
Aus Sicherheitsgründen stehen Geheimnisse wie Ihr BENCHER_API_TOKEN
und das GITHUB_TOKEN
nicht in GitHub-Aktionen für Fork-PRs zur Verfügung.
Das heißt, wenn ein externer Beitragender einen PR von einem Fork eröffnet, wird das obige Beispiel nicht funktionieren.
Es gibt drei Optionen für Fork-PRs:
- Benchmark Fork-PR vom Zielbranch
- Benchmark Fork-PR vom Zielbranch mit erforderlichen Prüfern
- Benchmark Fork-PR und Hochladen vom Standardbranch
Benchmark Fork-PR vom Zielbranch
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"
- Lauf
push
Events zurmain
Zweig und zupull_request_target
Events. - Erstellen Sie einen
job
der nur fürpush
Events zummain
Zweig läuft. Abgesehen von derif
Bedingung ist dieser Job fast identisch mit dem ursprünglichen Beispiel oben. - Erstellen Sie einen
job
der nur fürpull_request_target
Events läuft.- Checkout des Pull-Anfrage-Zweigs.
- Übergeben Sie alle Geheimnisse direkt. Verwenden Sie
--token ${{ secrets.BENCHER_API_TOKEN }}
anstelle derBENCHER_API_TOKEN
Umgebungsvariable. - Führen Sie Ihre Pull-Anfrage-Benchmarks durch und verfolgen Sie diese mit
bencher run
.
Diese Einrichtung funktioniert, weil pull_request_target
im Kontext des Zielzweigs der Pull-Anfrage läuft,
wo Geheimnisse wie Ihr BENCHER_API_TOKEN
und das GITHUB_TOKEN
verfügbar sind.
Daher wird dieser Workflow nur dann ausgeführt, wenn er auf dem Ziel Zweig existiert.
Vermeiden Sie das Einstellen von Geheimnissen als Umgebungsvariablen, wie BENCHER_API_TOKEN
.
Übergeben Sie stattdessen das API-Token explizit an bencher run
. (z.B.: --token ${{ secrets.BENCHER_API_TOKEN }}
)
Siehe diese GitHub Security Lab Aufschreibung
und diesen Blogbeitrag
zur Vermeidung von pwn-Anfragen für einen vollständigen Überblick.
Benchmark Fork-PR vom Zielbranch mit erforderlichen Prüfern
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"
Diese Einrichtung ist genau die gleiche wie Benchmark Fork-PR vom Zielbranch
mit der zusätzlichen Anforderung der Genehmigung eines erforderlichen Prüfer vor jedem Lauf einer Fork-Pull-Anfrage.
Pull-Anfragen aus demselben Repository benötigen keine Genehmigung.
Um dies einzurichten, müssen Sie zwei GitHub Action-Umgebungen erstellen
(z.B.: Repo -> Einstellungen -> Umgebungen -> Neue Umgebung
).
Die interne
Umgebung sollte keine Schutzregeln für die Bereitstellung
haben.
Die externe
Umgebung sollte jedoch Erforderliche Prüfer
haben, die denen vertraut sind, die Fork PRs vor dem Benchmarking überprüfen.
Benchmark Fork PR und Hochladen vom Standard-Zweig
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
- Erstellen Sie eine
Run and Cache Benchmarks
Workflow-Datei. - Führen Sie Ihre Benchmarks bei
pull_request
Events durch. - Speichern Sie die Benchmark-Ergebnisse in einer Datei und laden Sie diese als Artefakt hoch.
- Laden Sie das
pull_request
Event als Artefakt hoch. - Erstellen Sie eine zweite Workflow-Datei,
Track Benchmarks
. - Verketten Sie
Track Benchmarks
mitRun and Cache Benchmarks
mit dem Eventworkflow_run
. - Extrahieren Sie die notwendigen Daten aus dem gecachten
pull_request
Event. - Verfolgen Sie die gecachten Benchmark-Ergebnisse mit
bencher run
. - Erstellen Sie eine dritte Workflow-Datei und verwenden Sie das ursprüngliche obige Beispiel, um
push
Events zurmain
Zweig auszuführen.
Diese Einrichtung funktioniert, weil workflow_run
im Kontext des Standardzweigs des Repositorys läuft,
wo Geheimnisse wie Ihr BENCHER_API_TOKEN
und das GITHUB_TOKEN
verfügbar sind.
Daher werden diese Workflows nur dann ausgeführt, wenn sie auf dem Standard Branch existieren.
Siehe Verwendung von Daten aus dem auslösenden Workflow für einen vollständigen Überblick.
Die Pull-Anfrage-Nummer, der Head-Zweig und der Base-Zweig, die im initialen Workflow verwendet wurden, müssen explizit übergeben werden, da sie innerhalb von workflow_run
nicht verfügbar sind.
🐰 Herzlichen Glückwunsch! Sie haben gelernt, wie man Bencher in GitHub-Aktionen verwendet! 🎉