summaryrefslogtreecommitdiff
path: root/.github/workflows
diff options
context:
space:
mode:
Diffstat (limited to '.github/workflows')
-rw-r--r--.github/workflows/benchmark-comment.yml90
-rw-r--r--.github/workflows/benchmark.yml103
2 files changed, 193 insertions, 0 deletions
diff --git a/.github/workflows/benchmark-comment.yml b/.github/workflows/benchmark-comment.yml
new file mode 100644
index 00000000..c095162e
--- /dev/null
+++ b/.github/workflows/benchmark-comment.yml
@@ -0,0 +1,90 @@
+name: Benchmark Comment
+
+on:
+ workflow_run:
+ workflows: [Benchmark]
+ types: [completed]
+
+jobs:
+ comment-pr:
+ name: Post benchmark comment
+ # Only run when triggered by a pull_request event and the benchmark succeeded.
+ if: >
+ github.event.workflow_run.conclusion == 'success' &&
+ github.event.workflow_run.event == 'pull_request'
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: read
+ actions: read
+ pull-requests: write
+ issues: write
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Download benchmark results
+ uses: actions/download-artifact@v4
+ with:
+ run-id: ${{ github.event.workflow_run.id }}
+ name: benchmark-results
+ path: current-results
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Download PR number
+ uses: actions/download-artifact@v4
+ with:
+ run-id: ${{ github.event.workflow_run.id }}
+ name: pr-number
+ path: .
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Read PR number
+ id: pr
+ run: echo "number=$(cat pr-number.txt)" >> "$GITHUB_OUTPUT"
+
+ - name: Fetch baseline from benchmark-data branch
+ run: |
+ git fetch origin benchmark-data 2>/dev/null || true
+ git show origin/benchmark-data:benchmark-history.json > baseline.json 2>/dev/null \
+ || echo "[]" > baseline.json
+
+ - name: Generate comparison comment
+ run: |
+ python .github/scripts/compare_benchmarks.py \
+ current-results/results.json \
+ baseline.json \
+ > comment.md
+
+ - name: Post or update PR comment
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const fs = require('fs');
+ const body = fs.readFileSync('comment.md', 'utf8');
+ const marker = '<!-- opendc-benchmark-comment -->';
+ const fullBody = marker + '\n' + body;
+ const prNumber = parseInt(fs.readFileSync('pr-number.txt', 'utf8').trim());
+
+ const { data: comments } = await github.rest.issues.listComments({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: prNumber,
+ });
+
+ const existing = comments.find(c => c.body.includes(marker));
+ if (existing) {
+ await github.rest.issues.updateComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ comment_id: existing.id,
+ body: fullBody,
+ });
+ } else {
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: prNumber,
+ body: fullBody,
+ });
+ }
diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml
new file mode 100644
index 00000000..69c3164f
--- /dev/null
+++ b/.github/workflows/benchmark.yml
@@ -0,0 +1,103 @@
+name: Benchmark
+
+on:
+ pull_request:
+ branches: [master]
+ push:
+ branches: [master]
+ workflow_dispatch:
+
+# Cancel in-flight benchmark runs for the same PR/branch so only the latest commit is benchmarked.
+concurrency:
+ group: benchmark-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ benchmark:
+ name: Run CIBenchmark
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: read
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Set up JDK 21
+ uses: actions/setup-java@v4
+ with:
+ java-version: "21"
+ distribution: temurin
+
+ - name: Set up Gradle
+ uses: gradle/actions/setup-gradle@v4
+
+ - name: Run CIBenchmark
+ run: >
+ ./gradlew :opendc-experiments:opendc-experiments-base:jmh
+ -PjmhIncludes=.*CIBenchmark.*
+
+ - name: Upload benchmark results
+ uses: actions/upload-artifact@v4
+ with:
+ name: benchmark-results
+ path: opendc-experiments/opendc-experiments-base/build/results/jmh/results.json
+ retention-days: 7
+
+ # Store the PR number so the comment workflow (which runs with write permissions)
+ # knows which PR to comment on. Only needed for pull_request runs.
+ - name: Save PR number
+ if: github.event_name == 'pull_request'
+ run: echo "${{ github.event.pull_request.number }}" > pr-number.txt
+
+ - name: Upload PR number
+ if: github.event_name == 'pull_request'
+ uses: actions/upload-artifact@v4
+ with:
+ name: pr-number
+ path: pr-number.txt
+ retention-days: 1
+
+ # ── Master push: store results on the benchmark-data branch ──────────────────
+ store-results:
+ name: Store benchmark results
+ if: github.event_name == 'push'
+ needs: benchmark
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: write
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Download current results
+ uses: actions/download-artifact@v4
+ with:
+ name: benchmark-results
+ path: current-results
+
+ - name: Check out or create benchmark-data branch
+ run: |
+ git fetch origin benchmark-data 2>/dev/null || true
+ if git rev-parse --verify origin/benchmark-data 2>/dev/null; then
+ git worktree add benchmark-data-dir origin/benchmark-data
+ else
+ git worktree add --orphan -b benchmark-data benchmark-data-dir
+ fi
+
+ - name: Update history
+ run: |
+ python .github/scripts/update_history.py \
+ current-results/results.json \
+ benchmark-data-dir \
+ "${{ github.sha }}"
+
+ - name: Commit and push
+ run: |
+ git -C benchmark-data-dir config user.name "github-actions[bot]"
+ git -C benchmark-data-dir config user.email "github-actions[bot]@users.noreply.github.com"
+ git -C benchmark-data-dir add benchmark-history.json
+ git -C benchmark-data-dir commit \
+ -m "chore: benchmark results for ${{ github.sha }}"
+ git -C benchmark-data-dir push origin HEAD:benchmark-data