Skip to content

Bot - Benchmark PR Comment #276

Bot - Benchmark PR Comment

Bot - Benchmark PR Comment #276

name: Bot - Benchmark PR Comment
on:
workflow_run:
workflows: ["Benchmarks"]
types: [completed]
permissions:
contents: read
pull-requests: write
actions: read
jobs:
comment:
if: github.event.workflow_run.event == 'pull_request'
runs-on: ubuntu-latest
steps:
- name: Download benchmarks artifact
uses: actions/github-script@v9
with:
script: |
const run_id = context.payload.workflow_run.id;
const { data: list } = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id,
});
const art = list.artifacts.find(a => a.name === 'benchmarks');
if (!art) {
core.setFailed('benchmarks artifact missing');
return;
}
const dl = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: art.id,
archive_format: 'zip',
});
const fs = require('fs');
fs.writeFileSync('benchmarks.zip', Buffer.from(dl.data));
- name: Unzip
run: |
mkdir -p bench
unzip -o benchmarks.zip -d bench
ls -la bench
- name: Post comment
uses: actions/github-script@v9
with:
github-token: ${{ secrets.HOMEBREW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const read = (p, fallback = '') => {
try { return fs.readFileSync(p, 'utf8'); } catch (_) { return fallback; }
};
const prRaw = read('bench/pr-number.txt').trim();
const pr_number = parseInt(prRaw, 10);
if (!pr_number) {
core.info('no PR number recorded; skipping');
return;
}
const report = read('bench/benchstat.txt', '(empty)');
const verdict = read('bench/verdict.txt');
const parse = key => {
const m = verdict.match(new RegExp("^" + key + "=(.+)$", "m"));
return m ? m[1].trim() : '';
};
const status = parse('status') || 'neutral';
const worse = parse('worse') || '0';
const better = parse('better') || '0';
const headers = {
regression: "### Benchmark report — regression detected",
improvement: "### Benchmark report — improvement detected",
neutral: "### Benchmark report — no significant change",
};
const body = [
headers[status] || headers.neutral,
`Metrics worse: **${worse}** · better: **${better}** (threshold: ±3%).`,
"",
"<details><summary>benchstat output</summary>",
"",
"```",
report.trim() || "(empty)",
"```",
"",
"</details>",
"",
"<sub>auto-generated by benchmarks.yml</sub>",
].join("\n");
const marker = "<sub>auto-generated by benchmarks.yml</sub>";
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr_number,
});
const existing = comments.find(c => c.body && c.body.includes(marker));
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr_number,
body,
});
}