Como usar o Bencher nas Ações do GitHub
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"
- Crie um arquivo de
workflow
das Ações do GitHub. (ex:.github/workflows/benchmark.yml
) - Execute em eventos de
push
para a branchmain
. Veja a documentaçãoon
das Ações do GitHub para uma visão geral completa. Veja também Pull Requests abaixo. - Crie uma
job
das Ações do GitHub. (ex:benchmark_with_bencher
) - O Projeto já deve existir. Definir a flag
--project
ou a variável de ambienteBENCHER_PROJECT
para o slug do Projeto ou UUID (ex:BENCHER_PROJECT: save-walter-white
). - O token API já deve existir. Adicione
BENCHER_API_TOKEN
como segredo do Repositório (ex:Repositório -> Configurações -> Segredos e variáveis -> Ações -> Novo segredo do repositório
). Defina a flag--token
ou a variável de ambienteBENCHER_API_TOKEN
para o token API. (ex:BENCHER_API_TOKEN: ${{ secrets.BENCHER_API_TOKEN }}
) - Opcional: Definir a flag
--testbed
ou a variável de ambienteBENCHER_TESTBED
para o slug do Testbed ou UUID. (ex:BENCHER_TESTBED: ubuntu-latest
) O Testbed deve já existir. Se isso não for definido, então o Testbedlocalhost
será usado. - Opcional: Defina a flag
--adapter
ou a variável de ambienteBENCHER_ADAPTER
para o nome do adaptador desejado. (ex:BENCHER_ADAPTER: json
) Se isso não for definido, então o Adaptadormagic
será usado. Veja adaptadores de harness de benchmark para uma visão geral completa. - Faça o checkout do seu código-fonte. (ex:
uses: actions/checkout@v3
) - Instale o CLI Bencher usando a Ação do GitHub. (ex:
uses: bencherdev/bencher@main
) - Monitore seus benchmarks com o subcomando CLI
bencher run
:- Opcional: Defina a flag
--branch
ou a variável de ambienteBENCHER_BRANCH
para o slug da Branch ou UUID. (ex:--branch main
) A Branch deve já existir. Se isso não for definido, então a Branchmain
será usada. - Definir o comando para falhar se um Alerta for gerado. (ex:
--err
) Para que um Alerta seja gerado, um Limite já deve existir. - Execute seus benchmarks e gere um Relatório a partir dos resultados. (ex:
"bencher mock"
)
- Opcional: Defina a flag
Pull Requests
Para detectar regressão de desempenho em Pull Requests, você precisará executar seus benchmarks em PRs.
Se você espera ter PRs apenas de branches dentro do mesmo repositório, então você pode simplesmente modificar o exemplo acima para também executar on
eventos de pull_request
.
⚠️ Esta solução só funciona se todos os PRs são do mesmo repositório! Veja Pull Requests de Forks abaixo.
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"
- Execute em eventos de
push
para a branchmain
e em eventos depull_request
. É importante limitar a execução empush
apenas para as branches selecionadas (ex:main
) para evitar que pushes para branches de PR sejam executados duas vezes! - Em vez de sempre usar a branch
main
, use as variáveis de ambiente padrão das Ações do GitHub para:- Use os dados da branch atual se já existirem. (ex:
--if-branch "$GITHUB_REF_NAME"
) - Crie um clone dos dados e limites da branch de destino do PR se já existirem. (ex:
--else-if-branch "$GITHUB_BASE_REF"
) - Caso contrário, crie um clone dos dados e limites da branch
main
. (ex:--else-if-branch main
) - Existem várias opções para definir a branch do projeto. Veja seleção de branch para uma visão geral completa.
- Use os dados da branch atual se já existirem. (ex:
- Defina o token de autenticação da API do GitHub. (ex:
--github-actions ${{ secrets.GITHUB_TOKEN }}
) Quando essa opção é definida como parte de um pull request, então os resultados serão adicionados ao pull request como um comentário. Isso usa a variável de ambienteGITHUB_TOKEN
das Ações do GitHub. - Veja a documentação do bencher run para uma visão geral completa de todas as maneiras de configurar o comentário do pull request com as flags
--ci-*
.
Pull Requests de Forks
Se você planeja aceitar pull requests de forks, como é frequentemente o caso em projetos de código aberto público,
então você precisará lidar com as coisas de maneira um pouco diferente.
Por motivos de segurança, segredos como seu BENCHER_API_TOKEN
e o GITHUB_TOKEN
não estão disponíveis nas Ações do GitHub para PRs de forks.
Ou seja, se um colaborador externo abrir um PR a partir de um fork, o exemplo acima não funcionará.
Existem três opções para PRs de forks:
- Benchmark PR Fork da Branch Alvo
- Benchmark PR Fork da Branch Alvo com Revisores Obrigatórios
- Benchmark PR Fork e Upload da Branch Padrão
Benchmark PR Fork da Branch Alvo
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"
- Execute em eventos de
push
para a branchmain
e em eventos depull_request_target
. - Crie uma
job
que só é executada para eventos depush
para a branchmain
. Além da condiçãoif
, esse trabalho é quase idêntico ao exemplo original acima. - Crie uma
job
que só é executada para eventos depull_request_target
.- Faça o checkout da branch do pull request.
- Passe todos os segredos diretamente. Use
--token ${{ secrets.BENCHER_API_TOKEN }}
em vez da variável de ambienteBENCHER_API_TOKEN
. - Execute e monitore seus benchmarks de pull request com
bencher run
.
Esta configuração funciona porque pull_request_target
é executado no contexto da branch alvo do pull request,
onde seus segredos como BENCHER_API_TOKEN
e GITHUB_TOKEN
estão disponíveis.
Portanto, esse workflow só será executado se existir na branch alvo.
Evite definir quaisquer segredos como variáveis de ambiente, como BENCHER_API_TOKEN
.
Em vez disso, passe explicitamente o token da API para bencher run
. (ex: --token ${{ secrets.BENCHER_API_TOKEN }}
)
Veja este artigo do GitHub Security Lab
e este post de blog
sobre a prevenção de solicitações pwn para uma visão geral completa.
Benchmark PR Fork da Branch Alvo com Revisores Obrigatórios
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"
Esta configuração é exatamente a mesma que Benchmark PR Fork da Branch Alvo
com a exigência adicional de aprovação de um Revisor Necessário antes de cada execução do fork do pull request.
Pull requests do mesmo repositório não requerem aprovação.
Para configurar isso, você precisa criar dois Ambientes de Ação do GitHub
(ex: Repo -> Configurações -> Ambientes -> Novo ambiente
).
O ambiente interno
não deve ter Regras de proteção de implantação
.
No entanto, o ambiente externo
deve ter Revisores necessários
definidos para aqueles confiáveis para revisar PRs de fork antes do benchmarking.
Benchmark PR Fork e Upload da Branch Padrão
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
- Crie um arquivo de workflow
Run and Cache Benchmarks
. - Execute seus benchmarks em eventos de
pull_request
. - Salve os resultados dos benchmarks em um arquivo e faça o upload deles como um artefato.
- Faça o upload do evento
pull_request
como um artefato. - Crie um segundo arquivo de workflow,
Track Benchmarks
. - Encadeie
Track Benchmarks
aRun and Cache Benchmarks
com o eventoworkflow_run
. - Extraia os dados necessários do evento
pull_request
armazenado em cache. - Monitore os resultados do benchmark armazenado em cache com
bencher run
. - Crie um terceiro arquivo de workflow e use o exemplo inicial acima para executar em eventos de
push
para a branchmain
.
Esta configuração funciona porque workflow_run
é executado no contexto da branch padrão do repositório,
onde seus segredos como BENCHER_API_TOKEN
e GITHUB_TOKEN
estão disponíveis.
Portanto, esses workflows só serão executados se existirem na branch padrão.
Veja usando dados do workflow que desencadeou para uma visão geral completa.
O número do pull request, a branch de origem e a branch base usada no workflow inicial devem ser passados explicitamente, pois eles não estão disponíveis dentro do workflow_run
.
🐰 Parabéns! Você aprendeu como usar o Bencher nas Ações do GitHub! 🎉