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_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. GitHub Actions workflow 파일을 생성합니다. (예: .github/workflows/benchmarks.yml)
  2. main 브랜치로 push 이벤트를 실행합니다. 전체 개요는 GitHub Actions on 문서를 참조하세요. 아래의 Pull Requests도 참조하세요.
  3. GitHub Actions job을 생성합니다. (예: benchmark_with_bencher)
  4. 프로젝트는 이미 존재해야 합니다. --project 플래그를 설정하거나 BENCHER_PROJECT 환경 변수를 프로젝트 slug 또는 UUID로 설정합니다. (예: BENCHER_PROJECT: save-walter-white)
  5. 선택 사항: --testbed 플래그를 설정하거나 BENCHER_TESTBED 환경 변수를 Testbed slug 또는 UUID로 설정합니다. (예: BENCHER_TESTBED: ubuntu-latest) Testbed는 반드시 존재해야 합니다. 이 값이 설정되지 않으면 localhost Testbed가 사용됩니다.
  6. 선택 사항: 원하는 어댑터 이름으로 --adapter' 플래그를 설정하거나 BENCHER_ADAPTER환경 변수를 설정합니다. (예:BENCHER_ADAPTER: json) 이 값이 설정되지 않으면 magic` 어댑터가 사용됩니다. 전체 개요는 벤치마킹 하네스 어댑터를 참조하세요.
  7. 소스 코드를 체크아웃합니다. (예: uses: actions/checkout@v4)
  8. GitHub Action을 사용하여 Bencher CLI를 설치합니다. (예: uses: bencherdev/bencher@main)
  9. bencher run CLI 하위 명령을 사용하여 벤치마크를 추적합니다:
    1. 선택 사항: --branch 플래그를 설정하거나 BENCHER_BRANCH 환경 변수를 Branch slug 또는 UUID로 설정합니다. (예: --branch main) Branch는 반드시 존재해야 합니다. 이 값이 설정되지 않으면 main Branch가 사용됩니다.
    2. API 토큰은 반드시 존재해야 합니다. BENCHER_API_TOKENRepository 비밀로 추가합니다. (예: Repo -> Settings -> Secrets and variables -> Actions -> New repository secret) --token 플래그를 설정하거나 BENCHER_API_TOKEN 환경 변수를 API 토큰으로 설정합니다. (예: --token ${{ secrets.BENCHER_API_TOKEN }})
    3. Alert이 생성될 경우 명령이 실패하도록 설정합니다. (예: --err) Alert이 생성되려면 Threshold가 이미 존재해야 합니다.
    4. 벤치마크를 실행하고 결과에서 보고서를 생성합니다. (예: "bencher mock")

Pull Requests

Pull Requests에서 성능 회귀를 잡으려면 PR에서 벤치마크를 실행해야 합니다. PR이 동일 레파지토리 내의 브랜치에서만 예상된다면 위의 예제를 간단히 수정하여 pull_request 이벤트에서도 실행할 수 있습니다.

⚠️ 이 솔루션은 모든 PR이 동일 레파지토리에서 오는 경우에만 작동합니다! 아래에 있는 Forks에서의 Pull Requests를 참조하세요.

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. GitHub Actions workflow 파일을 생성합니다. (예: .github/workflows/pr_benchmarks.yml)
  2. pull request가 동일한 저장소에서 온 경우에만 pull_request 이벤트에서 실행하십시오. Fork PRs를 처리하는 방법은 아래의 Fork에서의 Pull Requests를 참조하십시오.
  3. GITHUB_TOKEN에 대한 권한 설정pull-requests에 대해 write로 설정하십시오. GitHub 설정에 따라 이가 필요하지 않을 수 있습니다. 하지만 모든 조직과 개인 리포지토리는 2023년 2월 2일 이후에 생성된 경우, 이것이 기본 행동입니다. 전체 개요는 GitHub 문서를 참조하십시오.
  4. 사용할 브랜치를 선택하십시오:
    1. 이미 존재하는 현재 브랜치 데이터를 사용합니다. (예: --if-branch "$GITHUB_REF_NAME")
    2. 이미 존재하는 PR 타겟 브랜치 데이터와 임계값의 복제본을 생성합니다. (예: --else-if-branch "$GITHUB_BASE_REF")
    3. 그렇지 않으면, main 브랜치 데이터와 임계값의 복제본을 생성합니다. (예: --else-if-branch main)
  5. GitHub API 인증 토큰을 설정합니다. (예: --github-actions "${{ secrets.GITHUB_TOKEN }}") 이 옵션이 pull request의 일부로 설정되면, 결과가 pull request에 댓글로 추가됩니다. 이는 GitHub Actions의 GITHUB_TOKEN 환경 변수를 사용합니다.
  6. 모든 방법을 통해 pull request 댓글을 --ci-* 플래그로 설정하는 방법에 대한 전체 개요는 bencher run 문서를 참조하십시오.
  7. (표시되지 않음) 두 번째 GitHub Actions workflow 파일을 생성하고 위의 초기 예제를 사용하여 main 브랜치로 push 이벤트에서 실행하십시오. (예: .github/workflows/benchmarks.yml)

Forks에서의 Pull Requests

Forks에서 pull request를 받을 계획이라면, 종종 공개 소스 프로젝트에서 그런 경우가 종종 있습니다. 그런 다음, 몇 가지를 조금 다르게 처리해야 합니다. 보안상의 이유로, BENCHER_API_TOKEN과 같은 비밀과 GITHUB_TOKEN은 Fork PR의 GitHub Actions에서 사용할 수 없습니다. 즉, 외부 기여자가 Fork에서 PR을 열 경우 위의 예제는 작동하지 않습니다. Fork PR에 대한 두 가지 옵션이 있습니다:

Required Reviewers와 함께 Target Branch에서 Fork PR 벤치마크

⚠️ fork PR을 승인하기 전에 반드시 매우, 매우 철저하게 검토해야 합니다! 그렇지 않다면 pwn 요청이 발생할 수 있습니다!

직접적으로 cpw 요청으로부터 벗어나고 싶다면, 아래의 기본 브랜치에서의 프로프 PR 및 업로드 벤치마킹을 참조해 주세요.

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. GitHub Actions workflow 파일을 생성합니다. (예: .github/workflows/pr_benchmarks.yml)
  2. pull_request_target 이벤트에 대하여 실행합니다.
  3. 각 Branch pull request (external) 실행 전에 승인가 필요한 Reviewer에서 필요로 하는 fork_pr_requires_review라는 job을 만듭니다.
  4. fork_pr_requires_review에 종속된 세 번째 job을 만듭니다.
    1. Pull request 브랜치를 체크아웃하지만 git 자격 증명을 지속적으로 유지하지 않습니다. (예: persist-credentials: false)
    2. 믿을 수 없는 입력을 위해 모든 내용을 단일 인용문(')으로 감쌉니다. (예: --if-branch '${{ github.head_ref }}')
    3. 모든 시크릿을 직접 전달합니다. (예: --token "${{ secrets.BENCHER_API_TOKEN }}")
    4. bencher run으로 PR 벤치마크를 실행하고 추적합니다.
  5. (보이지 않음) 두 번째 GitHub Actions workflow 파일을 만들고 위의 초기 예제를 사용하여 main 브랜치로 push 이벤트를 실행합니다. (예: .github/workflows/benchmarks.yml)

이 설정이 동작는 이유는 pull_request_target이 pull request의 target branch 맥락에서 실행되며, BENCHER_API_TOKENGITHUB_TOKEN과 같은 비밀이 사용 가능하기 때문입니다. 따라서, 이 워크플로우는 target 브랜치에 존재할 경우에만 실행됩니다.

이를 구성하려면, 두 개의 GitHub Action 환경을 생성해야 합니다. (예: Repo -> Settings -> Environments -> New environment). internal 환경은 Deployment protection rules이 없어야 합니다. 그러나 external 환경은 벤치마킹하기 전에 Fork PR을 검토해야 하는 Required reviewers로 설정되어 있어야 합니다.

PR 브랜치 이름(head ref)을 한 개의 따옴표로 감싸는 것이 매우 중요합니다. (예: --if-branch '${{ github.head_ref }}') 그렇지 않으면 공격자가 명령 주입을 수행하는 악의적으로 명명된 브랜치를 생성할 수 있습니다. 이 GitHub Security Lab 보고서를 참조하세요.

GITHUB_TOKENBENCHER_API_TOKEN과 같은 어떤 비밀도 환경 변수로 설정하지 마세요. 대신에, 명시적으로 bencher run에 비밀을 전달하세요. (예: --token "${{ secrets.BENCHER_API_TOKEN }}") 이 GitHub Security Lab 보고서 그리고 이 블로그 글 을 참조하세요.

Default Branch에서 Fork PR 벤치마크와 업로드

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. Run and Cache Benchmarks 워크플로우 파일을 만듭니다. (예: .github/workflows/pr_benchmarks.yml)
  2. 워크플로우에서 모든 작업을 pull_request 이벤트에서 실행합니다.
  3. 벤치마크를 실행하고 결과를 파일로 저장합니다. (예: benchmark_results.json)
  4. 벤치마크 결과 파일을 아티팩트로 업로드합니다.
  5. pull_request 이벤트 객체를 아티팩트로 업로드합니다.
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. 두 번째 워크플로우 파일, Track Benchmarks를 만듭니다. (예: .github/workflows/track_benchmarks.yml)
  2. the workflow_run eventTrack BenchmarksRun and Cache Benchmarks에 연결합니다.
  3. 캐쉬된 벤치마크 결과와 pull_request 이벤트를 다운로드합니다.
  4. 캐쉬된 벤치마크 결과와 pull_request 이벤트를 추출합니다.
  5. pull_request 이벤트에서 필요한 데이터를 환경 변수로 내보냅니다.
  6. bencher run을 사용한 캐쉬된 벤치마크 결과를 추적합니다:
    1. 모든 믿을 수 없는 입력을 위해 모든 건을 단일 인용문(')으로 감쌉니다. (예: --if-branch '${{ env.PR_HEAD }}')
    2. Pull Request 번호를 명시적으로 전달합니다. (예: --ci-number '${{ env.PR_NUMBER }}')
    3. 벤치마크 결과 파일의 파일 경로를 전달합니다. (예: --file "$BENCHMARK_RESULTS")
  7. (보이지 않음) 세 번째 GitHub Actions workflow 파일을 만들고 위의 초기 예를 사용하여 main 브랜치로 push 이벤트를 실행합니다. (예: .github/workflows/benchmarks.yml)

이 설정은 workflow_run이 레파지토리의 기본 브랜치 맥락에서 실행되며, BENCHER_API_TOKENGITHUB_TOKEN과 같은 비밀이 사용가능하기 때문에 동작합니다. 따라서, 이 워크플로우는 기본 브랜치에 있을 경우에만 실행됩니다. See using data from the triggering workflow for a full overview. 초기 워크플로우에서 사용한 pull request 번호, head branch, base branch는 workflow_run 내에서는 사용할 수 없으므로 명시적으로 전달해야 합니다.

PR 브랜치 이름(head ref)을 한 개의 따옴표로 감싸는 것이 매우 중요합니다. (예: --if-branch '${{ env.PR_HEAD }}') 그렇지 않으면 공격자가 명령 주입을 수행하는 악의적으로 명명된 브랜치를 생성할 수 있습니다. 이 GitHub Security Lab 보고서를 참조하세요.

workflow 파일 Run and Cache Benchmarks에서 GITHUB_TOKENBENCHER_API_TOKEN과 같은 비밀을 환경 변수로 설정하지 마세요. See GitHub Security Lab 보고서 and 이 블로그 글를 참조하세요.



🐰 축하합니다! GitHub Actions에서 Bencher를 사용하는 방법을 배웠습니다! 🎉


계속 진행하기: 벤치마킹 개요 ➡

🤖 이 문서는 OpenAI GPT-4에 의해 자동으로 생성되었습니다. 정확하지 않을 수도 있고 오류가 있을 수도 있습니다. 오류를 발견하면 GitHub에서 문제를 열어주세요.