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"
  1. GitHub Actions workflow ファイルを作成します。(例: .github/workflows/benchmark.yml)
  2. main ブランチへの push イベントで実行します。全体的な概要については、GitHub Actions の on ドキュメンテーション をご覧ください。また、下記の Pull Requests もご覧ください。
  3. GitHub Actions job を作成します。(例: benchmark_with_bencher)
  4. プロジェクトはすでに存在している必要があります。--project フラグを設定するか、BENCHER_PROJECT 環境変数をプロジェクトのスラッグかUUIDに設定します (例: BENCHER_PROJECT: save-walter-white).
  5. 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 }}).
  6. 任意: --testbed フラグまたは BENCHER_TESTBED 環境変数にTestbedのスラッグまたはUUIDを設定します (例: BENCHER_TESTBED: ubuntu-latest). Testbedはすでに存在している必要があります。これが設定されていない場合、localhost Testbedが使用されます。
  7. 任意: --adapter フラグまたは BENCHER_ADAPTER 環境変数に希望するアダプター名を設定します (例: BENCHER_ADAPTER: json). これが設定されていない場合、magic アダプターが使用されます。全体の概要については、ベンチマークハーネスアダプターをご覧ください。
  8. ソースコードをチェックアウトします (例: uses: actions/checkout@v3).
  9. GitHub Action を使用してBencher CLIをインストールします (例: uses: bencherdev/bencher@main).
  10. bencher run CLIサブコマンドで、ベンチマークをトラックします:
    1. 任意: --branch フラグまたは BENCHER_BRANCH 環境変数にBranchのスラッグまたはUUIDを設定します (例: --branch main). Branchはすでに存在している必要があります。これが設定されていない場合、main Branchが使用されます。
    2. アラートが生成された場合にコマンドが失敗するように設定します (例: --err). アラートが生成されるためには、すでにしきい値が存在している必要があります。
    3. ベンチマークを実行し、結果からレポートを生成します (例: "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"
  1. mainブランチへの pushイベントとpull_requestイベントで実行します。pushすべての選択したブランチ(例: main)のみに制限することで、PRブランチへのプッシュが2回実行されるのを防ぎます!
  2. 常にmainブランチを使用する代わりに、GitHub Actionのデフォルトの環境変数 を使用して:
    1. すでに存在する場合は、現在のbranchのデータを使用します。(例: --if-branch "$GITHUB_REF_NAME")
    2. すでに存在する場合は、PRターゲットbranchのデータとしきい値をクローンします。(例: --else-if-branch "$GITHUB_BASE_REF")
    3. それ以外の場合は、main branchのデータとしきい値をクローンします。(例: --else-if-branch main)
    4. プロジェクトbranchを設定するためのいくつかのオプションがあります。全体の概要については、branch selection をご覧ください。
  3. GitHub APIの認証トークンを設定します。(例: --github-actions ${{ secrets.GITHUB_TOKEN }}) このオプションがプルリクエストの一部として設定されると、結果はプルリクエストにコメントとして追加されます。これはGitHub Actionsの GITHUB_TOKEN 環境変数を使用します。
  4. --ci-* フラグを使用したプルリクエストコメントの設定方法については、bencher run のドキュメンテーションを全面的にご覧ください。

Forks からの Pull Requests

公開されているオープンソースプロジェクトの場合と同様に、フォークからのプルリクエストを受け入れる予定の場合、少し異なった方法で処理する必要があります。 セキュリティ上の理由から、BENCHER_API_TOKENGITHUB_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"
  1. main ブランチへの push イベントと pull_request_target イベントで実行します。
  2. main ブランチへの push イベントのみで実行される job を作成します。if 条件を除けば、このジョブはオリジナルの例とほぼ同じです。
  3. pull_request_target イベントのみで実行される job を作成します。
    1. プルリクエストブランチをチェックアウトします。
    2. すべてのシークレットを直接渡します。BENCHER_API_TOKEN 環境変数の代わりに --token ${{ secrets.BENCHER_API_TOKEN }} を使用します。
    3. プルリクエストのベンチマークを bencher run で実行してトラックします。

このセットアップは pull_request_target がプルリクエストのターゲットブランチのコンテキストで実行されるため機能します、 ここではあなたの BENCHER_API_TOKENGITHUB_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
  1. Run and Cache Benchmarks ワークフローファイルを作成します。
  2. pull_request イベントでベンチマークを実行します。
  3. ベンチマークの結果をファイルに保存し、それらをアーティファクトとしてアップロードします。
  4. pull_request イベントをアーティファクトとしてアップロードします。
  5. 2つ目のワークフローファイル Track Benchmarks を作成します。
  6. workflow_run イベント を使用して Track BenchmarksRun and Cache Benchmarks にチェーンします。
  7. キャッシュした pull_request イベントから必要なデータを抽出します。
  8. キャッシュしたベンチマーク結果を bencher run でトラックします。
  9. 初期の例を使用して、main ブランチへの push イベントで3つ目のワークフローファイルを実行します。

このセットアップは workflow_run がリポジトリのデフォルトブランチのコンテキストで実行されるため機能します、 ここでは BENCHER_API_TOKENGITHUB_TOKEN などのシークレットが利用可能です。 したがって、これらのワークフローは、それが デフォルト ブランチに存在する場合にのみ実行されます。 初期のワークフローで使用されたプルリクエスト番号、ヘッドブランチ、ベースブランチは、workflow_run 内部では利用できませんので、明示的に渡す必要があります。 詳細は トリガーワークフローからのデータ使用をご覧ください。



🐰 おめでとうございます!GitHub ActionsでBencherの使用方法がわかりました! 🎉


次に進む: ベンチマーキングの概要 ➡

🤖 このドキュメントは OpenAI GPT-4 によって自動的に生成されました。 正確ではない可能性があり、間違いが含まれている可能性があります。 エラーを見つけた場合は、GitHub で問題を開いてください。.