Skip to content

Commit 095b95b

Browse files
authored
Merge pull request #5 from mohdaquib/readme-files
Readme files
2 parents 7afcba2 + 98836d1 commit 095b95b

3 files changed

Lines changed: 1060 additions & 1 deletion

File tree

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
name: Benchmark Report
2+
3+
# Runs on every push to main (i.e. after a PR is merged).
4+
# Executes the full benchmark suite, formats results as a before/after
5+
# Markdown table, and upserts a comment on the merged PR.
6+
#
7+
# Separated from ci.yml (which runs on pull_request) so that:
8+
# • CI gates block merging on the PR branch.
9+
# • This workflow posts the final measured numbers back to the PR
10+
# after merge, closing the feedback loop without blocking review.
11+
12+
on:
13+
push:
14+
branches: [main]
15+
# Allow manual re-runs from the Actions tab (useful for debugging
16+
# or re-posting a comment after a flaky emulator run).
17+
workflow_dispatch:
18+
19+
# Only one benchmark run at a time per branch.
20+
# cancel-in-progress: if a new push lands while benchmarks are running,
21+
# cancel the stale run — the new commit's numbers are more relevant.
22+
concurrency:
23+
group: benchmark-report-${{ github.ref }}
24+
cancel-in-progress: true
25+
26+
permissions:
27+
contents: read
28+
# Needed to post / update comments on pull requests and issues.
29+
issues: write
30+
pull-requests: write
31+
32+
jobs:
33+
benchmark-report:
34+
name: Run benchmarks → post PR comment
35+
runs-on: ubuntu-latest
36+
37+
steps:
38+
- uses: actions/checkout@v4
39+
40+
- name: Make gradlew executable
41+
run: chmod +x gradlew
42+
43+
- uses: actions/setup-java@v4
44+
with:
45+
java-version: 17
46+
distribution: temurin
47+
48+
- uses: gradle/actions/setup-gradle@v3
49+
50+
# KVM gives the emulator hardware-accelerated virtualisation on the
51+
# GitHub-hosted runner. Without this, the emulator is unusably slow.
52+
- name: Enable KVM
53+
run: |
54+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' \
55+
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
56+
sudo udevadm control --reload-rules
57+
sudo udevadm trigger --name-match=kvm
58+
59+
# continue-on-error: true so that the formatting and comment steps
60+
# always run, even when a benchmark test fails or an emulator flake
61+
# occurs. The formatter reads BENCHMARK_STATUS and adds a warning
62+
# banner to the comment in that case.
63+
- name: Run all benchmarks
64+
id: benchmarks
65+
continue-on-error: true
66+
uses: reactivecircus/android-emulator-runner@v2
67+
with:
68+
api-level: 34
69+
target: default
70+
arch: x86_64
71+
emulator-boot-timeout: 600
72+
disable-animations: true
73+
# Headless, no audio, no boot animation, software GPU:
74+
# reduces idle overhead so IsolationActivity launches within
75+
# Macrobenchmark's 45-second window even on a shared runner.
76+
emulator-options: -no-window -no-audio -no-boot-anim -gpu swiftshader_indirect
77+
script: |
78+
# Belt-and-suspenders: disable animations via adb even though
79+
# disable-animations:true already does this — guards against
80+
# any race between emulator boot and the action's adb commands.
81+
adb shell settings put global window_animation_scale 0
82+
adb shell settings put global transition_animation_scale 0
83+
adb shell settings put global animator_duration_scale 0
84+
./gradlew :benchmarks:connectedBenchmarkBenchmarkAndroidTest
85+
86+
# Write the formatted comment to a temp file so later steps can read
87+
# it without re-running the script. `if: always()` ensures this runs
88+
# even when the benchmarks step failed (continue-on-error does not
89+
# prevent skipping when an earlier step without c-o-e fails).
90+
- name: Format benchmark results
91+
if: always()
92+
env:
93+
BENCHMARK_STATUS: ${{ steps.benchmarks.outcome }}
94+
GITHUB_SHA: ${{ github.sha }}
95+
GITHUB_RUN_ID: ${{ github.run_id }}
96+
GITHUB_REPOSITORY: ${{ github.repository }}
97+
run: python3 benchmarks/BenchmarkReportFormatter.py > /tmp/benchmark_comment.md
98+
99+
# Always append the formatted comment to the workflow's step summary
100+
# so the results are visible in the Actions UI even without a PR.
101+
- name: Post to step summary
102+
if: always()
103+
run: cat /tmp/benchmark_comment.md >> $GITHUB_STEP_SUMMARY
104+
105+
# /repos/{owner}/{repo}/commits/{sha}/pulls returns the PR(s) that
106+
# introduced this commit. Works for regular merges and squash-merges.
107+
# Outputs an empty string for direct pushes (no associated PR).
108+
- name: Find merged PR for this commit
109+
if: always()
110+
id: find-pr
111+
env:
112+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
113+
run: |
114+
number=$(gh api \
115+
"repos/${{ github.repository }}/commits/${{ github.sha }}/pulls" \
116+
-H "Accept: application/vnd.github.groot-preview+json" \
117+
--jq '.[0].number // ""')
118+
echo "number=$number" >> $GITHUB_OUTPUT
119+
120+
# Upsert the comment: update the existing benchmark comment (identified
121+
# by the <!-- benchmark-report --> marker) rather than creating a new
122+
# one on every push. Falls through silently when no PR is found.
123+
- name: Upsert PR comment
124+
if: always() && steps.find-pr.outputs.number != ''
125+
uses: actions/github-script@v7
126+
env:
127+
PR_NUMBER: ${{ steps.find-pr.outputs.number }}
128+
with:
129+
script: |
130+
const fs = require('fs');
131+
const commentPath = '/tmp/benchmark_comment.md';
132+
133+
if (!fs.existsSync(commentPath)) {
134+
core.warning('benchmark_comment.md not found — skipping PR comment');
135+
return;
136+
}
137+
138+
const body = fs.readFileSync(commentPath, 'utf8');
139+
const marker = '<!-- benchmark-report -->';
140+
const prNumber = Number(process.env.PR_NUMBER);
141+
142+
// Paginate in case the PR has > 100 comments.
143+
const comments = await github.paginate(
144+
github.rest.issues.listComments,
145+
{
146+
owner: context.repo.owner,
147+
repo: context.repo.repo,
148+
issue_number: prNumber,
149+
}
150+
);
151+
152+
const existing = comments.find(c => c.body.includes(marker));
153+
154+
if (existing) {
155+
await github.rest.issues.updateComment({
156+
owner: context.repo.owner,
157+
repo: context.repo.repo,
158+
comment_id: existing.id,
159+
body,
160+
});
161+
core.info(`Updated benchmark comment ${existing.id} on PR #${prNumber}`);
162+
} else {
163+
await github.rest.issues.createComment({
164+
owner: context.repo.owner,
165+
repo: context.repo.repo,
166+
issue_number: prNumber,
167+
body,
168+
});
169+
core.info(`Created benchmark comment on PR #${prNumber}`);
170+
}
171+
172+
- name: Upload benchmark JSON
173+
if: always()
174+
uses: actions/upload-artifact@v4
175+
with:
176+
name: benchmark-report-results
177+
path: >
178+
benchmarks/build/outputs/connected_android_test_additional_output
179+
/**/*-benchmarkData.json
180+
if-no-files-found: warn

0 commit comments

Comments
 (0)