GitHub ActionsでBencherを使用する方法
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"
- GitHub Actions
workflow
ファイルを作成します。(例:.github/workflows/benchmark.yml
) main
ブランチへのpush
イベントで実行します。全体的な概要については、GitHub Actions のon
ドキュメンテーション をご覧ください。また、下記の Pull Requests もご覧ください。- GitHub Actions
job
を作成します。(例:benchmark_with_bencher
) - プロジェクトはすでに存在している必要があります。
--project
フラグを設定するか、BENCHER_PROJECT
環境変数をプロジェクトのスラッグかUUIDに設定します (例:BENCHER_PROJECT: save-walter-white
). - APIトークンはすでに存在している必要があります。
BENCHER_API_TOKEN
を リポジトリの シークレットとして追加します (例:Repo -> Settings -> Secrets and variables -> Actions -> New repository secret
).--token
フラグまたはBENCHER_API_TOKEN
環境変数にAPIトークンを設定します (例:BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }}
). - 任意:
--testbed
フラグまたはBENCHER_TESTBED
環境変数にTestbedのスラッグまたはUUIDを設定します (例:BENCHER_TESTBED: ubuntu-latest
). Testbedはすでに存在している必要があります。これが設定されていない場合、localhost
Testbedが使用されます。 - 任意:
--adapter
フラグまたはBENCHER_ADAPTER
環境変数に希望するアダプター名を設定します (例:BENCHER_ADAPTER: json
). これが設定されていない場合、magic
アダプターが使用されます。全体の概要については、ベンチマークハーネスアダプターをご覧ください。 - ソースコードをチェックアウトします (例:
uses: actions/checkout@v3
). - GitHub Action を使用してBencher CLIをインストールします (例:
uses: bencherdev/bencher@main
). bencher run
CLIサブコマンドで、ベンチマークをトラックします:- 任意:
--branch
フラグまたはBENCHER_BRANCH
環境変数にBranchのスラッグまたはUUIDを設定します (例:--branch main
). Branchはすでに存在している必要があります。これが設定されていない場合、main
Branchが使用されます。 - アラートが生成された場合にコマンドが失敗するように設定します (例:
--err
). アラートが生成されるためには、すでにしきい値が存在している必要があります。 - ベンチマークを実行し、結果からレポートを生成します (例:
"bencher mock"
).
- 任意:
Pull Requests
プルリクエストでパフォーマンスの後退を検知するためには、PRでベンチマークを実行する必要があります。
もし、同じレポジトリ内のブランチからのPRだけを期待するなら、上記の例を単純に修正して pull_request
イベントでも実行することができます。
⚠️ この解決策は、すべてのPRが 同じ レポジトリからの場合にのみ機能します! 下記の フォークからのプルリクエストをご覧ください。
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"
main
ブランチへのpush
イベントとpull_request
イベントで実行します。push
を すべての選択したブランチ(例:main
)のみに制限することで、PRブランチへのプッシュが2回実行されるのを防ぎます!- 常に
main
ブランチを使用する代わりに、GitHub Actionのデフォルトの環境変数 を使用して:- すでに存在する場合は、現在のbranchのデータを使用します。(例:
--if-branch "$GITHUB_REF_NAME"
) - すでに存在する場合は、PRターゲットbranchのデータとしきい値をクローンします。(例:
--else-if-branch "$GITHUB_BASE_REF"
) - それ以外の場合は、
main
branchのデータとしきい値をクローンします。(例:--else-if-branch main
) - プロジェクトbranchを設定するためのいくつかのオプションがあります。全体の概要については、branch selection をご覧ください。
- すでに存在する場合は、現在のbranchのデータを使用します。(例:
- GitHub APIの認証トークンを設定します。(例:
--github-actions ${{ secrets.GITHUB_TOKEN }}
) このオプションがプルリクエストの一部として設定されると、結果はプルリクエストにコメントとして追加されます。これはGitHub ActionsのGITHUB_TOKEN
環境変数を使用します。 --ci-*
フラグを使用したプルリクエストコメントの設定方法については、bencher run のドキュメンテーションを全面的にご覧ください。
Forks からの Pull Requests
公開されているオープンソースプロジェクトの場合と同様に、フォークからのプルリクエストを受け入れる予定の場合、少し異なった方法で処理する必要があります。
セキュリティ上の理由から、BENCHER_API_TOKEN
やGITHUB_TOKEN
などのシークレットは、fork PRのGitHub Actionsで利用できません。
つまり、外部のコントリビュータがフォークからPRを開くと、上記の例は機能しません。
フォークPRには以下の3つのオプションが存在します。
ターゲットブランチからのフォークPRのベンチマーク
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"
main
ブランチへのpush
イベントとpull_request_target
イベントで実行します。main
ブランチへのpush
イベントのみで実行されるjob
を作成します。if
条件を除けば、このジョブはオリジナルの例とほぼ同じです。pull_request_target
イベントのみで実行されるjob
を作成します。- プルリクエストブランチをチェックアウトします。
- すべてのシークレットを直接渡します。
BENCHER_API_TOKEN
環境変数の代わりに--token ${{ secrets.BENCHER_API_TOKEN }}
を使用します。 - プルリクエストのベンチマークを
bencher run
で実行してトラックします。
このセットアップは pull_request_target
がプルリクエストのターゲットブランチのコンテキストで実行されるため機能します、
ここではあなたの BENCHER_API_TOKEN
や GITHUB_TOKEN
などのシークレットが利用可能です。
したがって、このワークフローは、それが ターゲット ブランチに存在する場合にのみ実行されます。
シークレットを環境変数として設定するのは避けてください、例えば BENCHER_API_TOKEN
など。
代わりに APIトークンを bencher run
へ明示的に渡してください (例: --token ${{ secrets.BENCHER_API_TOKEN }}
).
完全な概観については、この GitHubセキュリティラボの書き込み と
this blog post をご覧ください。
必須レビュワー付きのターゲットブランチからのフォークPRのベンチマーク
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"
このセットアップはターゲットブランチからのフォークPRのベンチマークと全く同じですが、
フォークからの各プルリクエストの実行前に、必須のレビュワーからの承認が必要となる追加の要求事項があります。
同じリポジトリからのプルリクエストには承認が必要ありません。
これをセットアップするためには、2つのGitHub Action Environmentsを作成する必要があります (例: Repo -> Settings -> Environments -> New environment
).
internal
環境にはDeployment protection rules
は設定せず、
external
環境はベンチマーキング前にフォークPRをレビューしたと信頼できる者をRequired reviewers
に設定します。
デフォルトブランチからのフォークPRとアップロード
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
Run and Cache Benchmarks
ワークフローファイルを作成します。pull_request
イベントでベンチマークを実行します。- ベンチマークの結果をファイルに保存し、それらをアーティファクトとしてアップロードします。
pull_request
イベントをアーティファクトとしてアップロードします。- 2つ目のワークフローファイル
Track Benchmarks
を作成します。 -
workflow_run
イベント を使用してTrack Benchmarks
をRun and Cache Benchmarks
にチェーンします。 - キャッシュした
pull_request
イベントから必要なデータを抽出します。 - キャッシュしたベンチマーク結果を
bencher run
でトラックします。 - 初期の例を使用して、
main
ブランチへのpush
イベントで3つ目のワークフローファイルを実行します。
このセットアップは workflow_run
がリポジトリのデフォルトブランチのコンテキストで実行されるため機能します、
ここでは BENCHER_API_TOKEN
や GITHUB_TOKEN
などのシークレットが利用可能です。
したがって、これらのワークフローは、それが デフォルト ブランチに存在する場合にのみ実行されます。
初期のワークフローで使用されたプルリクエスト番号、ヘッドブランチ、ベースブランチは、workflow_run
内部では利用できませんので、明示的に渡す必要があります。
詳細は トリガーワークフローからのデータ使用をご覧ください。
🐰 おめでとうございます!GitHub ActionsでBencherの使用方法がわかりました! 🎉