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
) push
이벤트를main
브랜치로 실행합니다. 전체 개요는 GitHub Actionson
문서를 참조하세요. 또한 아래의 Pull Requests도 참조하세요.- GitHub Actions
job
를 생성합니다. (예:benchmark_with_bencher
) - 프로젝트는 이미 존재해야 합니다.
--project
플래그를 설정하거나BENCHER_PROJECT
환경 변수를 프로젝트 슬러그나 UUID로 설정합니다. (예:BENCHER_PROJECT: save-walter-white
). - API 토큰은 이미 존재해야 합니다.
BENCHER_API_TOKEN
을 레포지토리 시크릿으로 추가합니다. (예:저장소 -> 설정 -> 시크릿 및 변수 -> 작업 -> 새 레포지토리 시크릿
)--token
플래그를 설정하거나BENCHER_API_TOKEN
환경 변수를 API 토큰으로 설정합니다. (예:BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }}
) - 선택 사항:
--testbed
플래그를 설정하거나BENCHER_TESTBED
환경 변수를 테스트 베드 슬러그나 UUID로 설정합니다. (예:BENCHER_TESTBED: ubuntu-latest
) 테스트 베드는 반드시 이미 존재해야 합니다. 만약 이것을 설정하지 않으면,localhost
테스트 베드가 사용되게 됩니다. - 선택 사항:
--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
환경 변수를 브랜치 슬러그나 UUID로 설정합니다. (예:--branch main
) 브랜치는 반드시 이미 존재해야 합니다. 만약 이것을 설정하지 않으면,main
브랜치가 사용되게 됩니다. - 경고가 생성되면 명령이 실패하도록 설정합니다. (예:
--err
) 경고가 생성되기 위해서는, 임계값이 이미 존재해야 합니다. - 벤치마크를 실행하고 결과에서 보고서를 생성합니다. (예:
"bencher mock"
)
- 선택 사항:
Pull Requests
Pull Request에서 성능 회귀를 잡아내기 위해 PR에서 벤치마크를 실행해야 합니다.
당신이 같은 저장소 내의 브랜치로부터 PR만 받을 것이라고 예상한다면, 위의 예제를 수정해서 on
pull_request
이벤트에서도 실행하게 하십시오.
⚠️ 이 해결책은 모든 PR들이 같은 저장소에서 오는 경우에만 작동합니다! 아래의 Fork들로부터의 Pull Requests를 참조하세요.
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"
push
이벤트를main
브랜치로 실행하고pull_request
이벤트에서도 실행합니다. PR 브랜치에 대한 push가 두 번 실행되는 것을 막기 위해,push
를 선택된 브랜치(예:main
)로 만 실행하는 것이 중요합니다!- 항상
main
브랜치를 사용하는 대신에, GitHub Action 기본 환경 변수를 사용하여:- 현재 브랜치 데이터가 이미 존재하면 이를 사용합니다. (예:
--if-branch "$GITHUB_REF_NAME"
) - PR 대상 브랜치 데이터와 임계값이 이미 존재하면 이를 복제해서 만듭니다. (예:
--else-if-branch "$GITHUB_BASE_REF"
) - 그 외의 경우,
main
브랜치 데이터와 임계값을 복제해서 만듭니다. (예:--else-if-branch main
) - 프로젝트 브랜치를 설정하는 데는 여러 가지 옵션이 있습니다. 전체 개요는 브랜치 선택을 참조하세요.
- 현재 브랜치 데이터가 이미 존재하면 이를 사용합니다. (예:
- GitHub API 인증 토큰을 설정합니다. (예:
--github-actions ${{ secrets.GITHUB_TOKEN }}
) 이 옵션이 pull request의 일부로 설정되면, 결과가 pull request에 댓글로 추가됩니다. 이는 GitHub ActionsGITHUB_TOKEN
환경 변수를 사용합니다. --ci-*
플래그로 pull request 댓글을 설정하는 모든 방법에 대한 전체 개요는 bencher run 문서를 참조하세요.
Fork들로부터의 Pull Requests
당신이 공개 오픈 소스 프로젝트에서 종종 하는 경우처럼 fork들로부터 pull request를 받을 계획이라면, 소소하게 다른 방식으로 처리해야 합니다.
보안 문제로 인해, BENCHER_API_TOKEN
및 GITHUB_TOKEN
과 같은 비밀 정보는 fork PRs에서의 GitHub Actions을 사용할 수 없습니다.
즉, 외부 기여자가 fork에서 PR을 열면 위의 예시는 작동하지 않게 됩니다.
fork PRs에는 세 가지 옵션이 있습니다:
- Target Branch로부터 Fork PR를 벤치마크
- 필수 리뷰어가 있는 Target Branch로부터 Fork PR를 벤치마크
- 기본 Branch로부터 Fork PR를 벤치마크하고 업로드
Target Branch로부터 Fork 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"
push
이벤트를main
브랜치로 실행하고 onpull_request_target
events를 실행합니다.push
이벤트를main
브랜치로만 실행하는job
을 생성합니다.if
조건을 제외하고, 이 job은 원래의 예제와 거의 동일합니다.pull_request_target
이벤트를 실행하는job
을 생성합니다.- pull request 브랜치를 체크아웃합니다.
- 모든 비밀 정보를 직접 전달합니다.
BENCHER_API_TOKEN
환경 변수 대신--token ${{ secrets.BENCHER_API_TOKEN }}
을 사용합니다. bencher run
을 사용하여 pull request의 벤치마크를 실행하고 추적합니다.
이 설정이 작동하는 이유는 pull_request_target
이 pull request의 대상 브랜치로 실행되는 컨텍스트 내에서 실행되기 때문이며, 이곳에서는 BENCHER_API_TOKEN
및 GITHUB_TOKEN
과 같은 비밀 정보가 사용 가능합니다.
따라서, 이 워크플로우는 target 브랜치에 존재하는 경우에만 실행됩니다.
BENCHER_API_TOKEN
과 같은 비밀 정보를 환경 변수로 설정하지 마십시오.
대신 명시적으로 API 토큰을 bencher run
에 전달하십시오. (예: --token ${{ secrets.BENCHER_API_TOKEN }}
)
전체 개요는 GitHub Security Lab 글
및 이 블로그 게시물
에서 pwn 요청을 방지하는 방법을 확인할 수 있습니다.
필수 리뷰어가 있는 Target Branch로부터 Fork 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"
이 설정은 Target Branch로부터 Fork PR를 벤치마크
와 완전히 동일하지만, 각 fork pull request 실행 전에 필수 리뷰어의 승인이 필요로 하는 추가 요건이 있습니다.
같은 저장소에서 온 pull request는 승인이 필요하지 않습니다.
이를 설정하려면, 두 개의 GitHub Action 환경을 생성
해야 합니다 (예: 저장소 -> 설정 -> 환경 -> 새로운 환경
).
internal
환경에는 Deploy protection rules
가 없어야 합니다.
그러나 external
환경에는 벤치마킹 전에 fork PRs를 검토할 수 있는 사람들이 필수 리뷰어
로 설정되어야 합니다.
기본 Branch로부터 Fork 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
이벤트를 아티팩트로 업로드합니다.- 두 번째 워크플로우 파일인
Track Benchmarks
를 생성합니다. workflow_run
이벤트를 사용하여Track Benchmarks
를Run and Cache Benchmarks
에 연결합니다.- 캐시된
pull_request
이벤트에서 필요한 데이터를 추출합니다. - 캐시된 벤치마크 결과를
bencher run
으로 추적합니다. push
이벤트를main
브랜치로 실행하는 초기 예를 사용하여 세 번째 워크플로우 파일을 생성합니다.
이 설정은 workflow_run
이 레포지토리의 기본 브랜치 컨텍스트 내에서 실행되므로 작동합니다.
따라서, BENCHER_API_TOKEN
및 GITHUB_TOKEN
과 같은 비밀 정보가 사용 가능합니다.
따라서, 이 워크플로우는 default 브랜치에 존재하는 경우에만 실행됩니다.
전체 개요는 트리거 워크플로우에서 데이터 사용하기를 참조할 수 있습니다.
초기 워크플로우에서 사용된 pull request 번호, 헤드 브랜치, 및 기본 브랜치는 workflow_run
내에서는 사용할 수 없으므로 명시적으로 전달해야 합니다.
🐰 축하합니다! GitHub Actions에서 Bencher를 어떻게 사용하는지 배웠습니다! 🎉