Skip to content

Commit c07b9e1

Browse files
authored
Merge pull request #2 from javalin/norrs/pr-previews-side-by-side
[actions] Publish PR previews side-by-side with main Pages site
2 parents 4450cd9 + 61dd7d9 commit c07b9e1

4 files changed

Lines changed: 273 additions & 15 deletions

File tree

.github/workflows/benchmark-pages.yml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,18 +215,19 @@ jobs:
215215
RUN_ID: ${{ needs.prepare.outputs.run_id }}
216216
GITHUB_TOKEN: ${{ github.token }}
217217
GITHUB_REPOSITORY: ${{ github.repository }}
218+
BENCHMARK_DATA_BRANCH: ${{ vars.BENCHMARK_DATA_BRANCH || 'benchmark-data' }}
218219
run: |
219220
set -euo pipefail
220221
221222
repo_url="https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
222223
223-
if git ls-remote --exit-code --heads "$repo_url" benchmark-data >/dev/null 2>&1; then
224-
git clone --depth 1 --branch benchmark-data "$repo_url" benchmark-history
224+
if git ls-remote --exit-code --heads "$repo_url" "${BENCHMARK_DATA_BRANCH}" >/dev/null 2>&1; then
225+
git clone --depth 1 --branch "${BENCHMARK_DATA_BRANCH}" "$repo_url" benchmark-history
225226
else
226227
mkdir benchmark-history
227228
pushd benchmark-history >/dev/null
228229
git init
229-
git checkout -b benchmark-data
230+
git checkout -b "${BENCHMARK_DATA_BRANCH}"
230231
git remote add origin "$repo_url"
231232
popd >/dev/null
232233
fi
@@ -243,7 +244,7 @@ jobs:
243244
echo "No new benchmark data to commit"
244245
else
245246
git commit -m "Add benchmark run ${RUN_ID}"
246-
git push origin HEAD:benchmark-data
247+
git push origin HEAD:"${BENCHMARK_DATA_BRANCH}"
247248
fi
248249
popd >/dev/null
249250
@@ -257,6 +258,11 @@ jobs:
257258
--output-dir site \
258259
--repository "${GITHUB_REPOSITORY}"
259260
261+
if [ -d benchmark-history/pr-previews ]; then
262+
mkdir -p site/pr-previews
263+
cp -R benchmark-history/pr-previews/. site/pr-previews/
264+
fi
265+
260266
- name: Configure Pages
261267
uses: actions/configure-pages@v5
262268

.github/workflows/benchmark-pr.yml

Lines changed: 119 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@ name: Benchmark PR
22

33
on:
44
pull_request:
5+
types:
6+
- opened
7+
- synchronize
8+
- reopened
9+
- ready_for_review
510
workflow_dispatch:
611
inputs:
712
versions:
@@ -58,7 +63,9 @@ on:
5863
type: string
5964

6065
permissions:
61-
contents: read
66+
contents: write
67+
pages: write
68+
id-token: write
6269

6370
concurrency:
6471
group: benchmark-pr-${{ github.event.pull_request.number || github.event.inputs.sourcePrNumber || github.run_id }}
@@ -80,6 +87,7 @@ jobs:
8087
INPUT_TRIGGER_REPOSITORY: ${{ github.event.inputs.triggerRepository }}
8188
INPUT_TRIGGER_PR_NUMBER: ${{ github.event.inputs.triggerPrNumber }}
8289
INPUT_TRIGGER_PR_URL: ${{ github.event.inputs.triggerPrUrl }}
90+
GH_EVENT_PR_NUMBER: ${{ github.event.pull_request.number || '' }}
8391
PR_OR_RUN_ID: ${{ github.event.pull_request.number || github.event.inputs.sourcePrNumber || github.run_id }}
8492
GITHUB_REPOSITORY: ${{ github.repository }}
8593
GITHUB_WORKFLOW: ${{ github.workflow }}
@@ -89,6 +97,8 @@ jobs:
8997
GITHUB_REF_NAME: ${{ github.ref_name }}
9098
GITHUB_TOKEN: ${{ github.token }}
9199
PERFORMANCE_TESTS_TRIGGER_TOKEN: ${{ secrets.PERFORMANCE_TESTS_TRIGGER_TOKEN }}
100+
BENCHMARK_DATA_BRANCH: ${{ vars.BENCHMARK_DATA_BRANCH || 'benchmark-data' }}
101+
PR_PREVIEW_BASE_URL: ${{ vars.PR_PREVIEW_PAGES_BASE_URL || 'https://javalin.github.io/javalin-performance-tests-testing/pr-previews' }}
92102
steps:
93103
- name: Checkout
94104
uses: actions/checkout@v4
@@ -113,7 +123,8 @@ jobs:
113123
source_dir="$(mktemp -d)"
114124
git clone "https://github.com/${INPUT_SOURCE_REPOSITORY}.git" "${source_dir}"
115125
pushd "${source_dir}" >/dev/null
116-
git checkout "${INPUT_SOURCE_REF}"
126+
checkout_target="${INPUT_SOURCE_REF:-${INPUT_SOURCE_SHA}}"
127+
git checkout "${checkout_target}"
117128
chmod +x ./mvnw
118129
snapshot_version="$(./mvnw -q -DforceStdout help:evaluate -Dexpression=project.version | tail -n 1 | tr -d '\r')"
119130
if [ -z "${snapshot_version}" ]; then
@@ -191,11 +202,19 @@ jobs:
191202
mkdir -p pr-history/runs
192203
repo_url="https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
193204
194-
if git ls-remote --exit-code --heads "$repo_url" benchmark-data >/dev/null 2>&1; then
195-
git clone --depth 1 --branch benchmark-data "$repo_url" benchmark-history
196-
if [ -d benchmark-history/runs ]; then
197-
cp -R benchmark-history/runs/. pr-history/runs/
198-
fi
205+
if git ls-remote --exit-code --heads "$repo_url" "${BENCHMARK_DATA_BRANCH}" >/dev/null 2>&1; then
206+
git clone --depth 1 --branch "${BENCHMARK_DATA_BRANCH}" "$repo_url" benchmark-history
207+
else
208+
mkdir benchmark-history
209+
pushd benchmark-history >/dev/null
210+
git init
211+
git checkout -b "${BENCHMARK_DATA_BRANCH}"
212+
git remote add origin "$repo_url"
213+
popd >/dev/null
214+
fi
215+
216+
if [ -d benchmark-history/runs ]; then
217+
cp -R benchmark-history/runs/. pr-history/runs/
199218
fi
200219
201220
RUN_ID="$(python3 -c 'import json; print(json.load(open("current-run/run-metadata.json"))["runId"])')"
@@ -207,6 +226,95 @@ jobs:
207226
--output-dir pr-site \
208227
--repository "${GITHUB_REPOSITORY}"
209228
229+
- name: Resolve PR preview target
230+
id: preview_target
231+
run: |
232+
set -euo pipefail
233+
234+
pr_number="${INPUT_SOURCE_PR_NUMBER:-${INPUT_TRIGGER_PR_NUMBER:-${GH_EVENT_PR_NUMBER:-}}}"
235+
run_id="$(python3 -c 'import json; print(json.load(open("current-run/run-metadata.json"))["runId"])')"
236+
237+
if [ -z "${pr_number}" ]; then
238+
echo "No PR number resolved; skipping PR preview publishing."
239+
echo "has_pr_number=false" >> "$GITHUB_OUTPUT"
240+
exit 0
241+
fi
242+
243+
preview_root="pr-${pr_number}"
244+
preview_run_dir="${preview_root}/${run_id}"
245+
preview_latest_dir="${preview_root}/latest"
246+
base_url="${PR_PREVIEW_BASE_URL%/}"
247+
248+
echo "has_pr_number=true" >> "$GITHUB_OUTPUT"
249+
echo "pr_number=${pr_number}" >> "$GITHUB_OUTPUT"
250+
echo "preview_root=${preview_root}" >> "$GITHUB_OUTPUT"
251+
echo "preview_run_dir=${preview_run_dir}" >> "$GITHUB_OUTPUT"
252+
echo "preview_latest_dir=${preview_latest_dir}" >> "$GITHUB_OUTPUT"
253+
echo "preview_run_url=${base_url}/${preview_run_dir}/" >> "$GITHUB_OUTPUT"
254+
echo "preview_latest_url=${base_url}/${preview_latest_dir}/" >> "$GITHUB_OUTPUT"
255+
256+
- name: Publish PR preview content to benchmark-data branch
257+
if: ${{ steps.preview_target.outputs.has_pr_number == 'true' }}
258+
run: |
259+
set -euo pipefail
260+
261+
preview_run_path="pr-previews/${{ steps.preview_target.outputs.preview_run_dir }}"
262+
preview_latest_path="pr-previews/${{ steps.preview_target.outputs.preview_latest_dir }}"
263+
preview_root_path="pr-previews/${{ steps.preview_target.outputs.preview_root }}"
264+
265+
rm -rf "benchmark-history/${preview_run_path}" "benchmark-history/${preview_latest_path}"
266+
mkdir -p "benchmark-history/${preview_run_path}" "benchmark-history/${preview_latest_path}"
267+
cp -R pr-site/. "benchmark-history/${preview_run_path}/"
268+
cp -R pr-site/. "benchmark-history/${preview_latest_path}/"
269+
270+
pushd benchmark-history >/dev/null
271+
git config user.name "github-actions[bot]"
272+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
273+
git add "${preview_root_path}"
274+
275+
if git diff --cached --quiet; then
276+
echo "No preview page changes to commit."
277+
else
278+
git commit -m "Update PR preview ${preview_root_path}"
279+
git push origin HEAD:"${BENCHMARK_DATA_BRANCH}"
280+
fi
281+
popd >/dev/null
282+
283+
- name: Build deployable site (main + PR previews)
284+
run: |
285+
set -euo pipefail
286+
mkdir -p benchmark-history/runs
287+
python3 scripts/generate_pages.py \
288+
--history-root benchmark-history/runs \
289+
--output-dir site \
290+
--repository "${GITHUB_REPOSITORY}"
291+
292+
if [ -d benchmark-history/pr-previews ]; then
293+
mkdir -p site/pr-previews
294+
cp -R benchmark-history/pr-previews/. site/pr-previews/
295+
fi
296+
297+
- name: Configure Pages
298+
uses: actions/configure-pages@v5
299+
300+
- name: Upload Pages artifact
301+
uses: actions/upload-pages-artifact@v3
302+
with:
303+
path: site
304+
305+
- name: Deploy to GitHub Pages
306+
id: deploy
307+
uses: actions/deploy-pages@v4
308+
309+
- name: Add PR preview links to job summary
310+
if: ${{ steps.preview_target.outputs.has_pr_number == 'true' }}
311+
run: |
312+
{
313+
echo "### PR Preview Links"
314+
echo "- Latest: ${{ steps.preview_target.outputs.preview_latest_url }}"
315+
echo "- This run: ${{ steps.preview_target.outputs.preview_run_url }}"
316+
} >> "$GITHUB_STEP_SUMMARY"
317+
210318
- name: Add summary to job page
211319
run: |
212320
python3 scripts/print_summary_markdown.py pr-site/summary.json --limit 60 >> "$GITHUB_STEP_SUMMARY"
@@ -229,13 +337,16 @@ jobs:
229337
const [owner, repo] = process.env.INPUT_TRIGGER_REPOSITORY.split("/");
230338
const prNumber = parseInt(process.env.INPUT_TRIGGER_PR_NUMBER, 10);
231339
const runUrl = `https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`;
340+
const previewUrl = `${{ steps.preview_target.outputs.preview_latest_url }}`;
341+
const previewLine = previewUrl ? `- [View PR preview page](${previewUrl})\n` : "";
232342
await github.rest.issues.createComment({
233343
owner,
234344
repo,
235345
issue_number: prNumber,
236346
body:
237347
"Performance benchmark completed successfully.\n\n" +
238-
`- [View benchmark results](${runUrl})`,
348+
`- [View benchmark workflow run](${runUrl})\n` +
349+
previewLine,
239350
});
240351
241352
- name: Comment benchmark failure on triggering PR
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
name: Cleanup PR Preview
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
prNumber:
7+
description: 'PR number whose preview should be removed'
8+
required: true
9+
type: string
10+
11+
permissions:
12+
contents: write
13+
pages: write
14+
id-token: write
15+
16+
jobs:
17+
cleanup:
18+
runs-on: ubuntu-latest
19+
env:
20+
INPUT_PR_NUMBER: ${{ github.event.inputs.prNumber }}
21+
BENCHMARK_DATA_BRANCH: ${{ vars.BENCHMARK_DATA_BRANCH || 'benchmark-data' }}
22+
PR_PREVIEW_BASE_URL: ${{ vars.PR_PREVIEW_PAGES_BASE_URL || 'https://javalin.github.io/javalin-performance-tests-testing/pr-previews' }}
23+
steps:
24+
- name: Checkout
25+
uses: actions/checkout@v4
26+
27+
- name: Set up Python
28+
uses: actions/setup-python@v5
29+
with:
30+
python-version: '3.x'
31+
32+
- name: Validate inputs
33+
run: |
34+
set -euo pipefail
35+
case "${INPUT_PR_NUMBER}" in
36+
''|*[!0-9]*)
37+
echo "Invalid prNumber: ${INPUT_PR_NUMBER}" >&2
38+
exit 1
39+
;;
40+
esac
41+
42+
- name: Remove preview directory from benchmark-data branch
43+
id: cleanup_preview
44+
env:
45+
GITHUB_TOKEN: ${{ github.token }}
46+
GITHUB_REPOSITORY: ${{ github.repository }}
47+
run: |
48+
set -euo pipefail
49+
50+
repo_url="https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
51+
preview_dir="pr-previews/pr-${INPUT_PR_NUMBER}"
52+
53+
if ! git ls-remote --exit-code --heads "$repo_url" "${BENCHMARK_DATA_BRANCH}" >/dev/null 2>&1; then
54+
echo "History branch ${BENCHMARK_DATA_BRANCH} does not exist; nothing to clean."
55+
echo "deleted=false" >> "$GITHUB_OUTPUT"
56+
exit 0
57+
fi
58+
59+
git clone --depth 1 --branch "${BENCHMARK_DATA_BRANCH}" "$repo_url" benchmark-history
60+
pushd benchmark-history >/dev/null
61+
62+
if [ ! -d "${preview_dir}" ]; then
63+
echo "Preview path ${preview_dir} does not exist; nothing to clean."
64+
echo "deleted=false" >> "$GITHUB_OUTPUT"
65+
exit 0
66+
fi
67+
68+
rm -rf "${preview_dir}"
69+
git config user.name "github-actions[bot]"
70+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
71+
git add -A "${preview_dir}"
72+
73+
if git diff --cached --quiet; then
74+
echo "No preview deletions to commit."
75+
echo "deleted=false" >> "$GITHUB_OUTPUT"
76+
exit 0
77+
fi
78+
79+
git commit -m "Remove PR preview ${preview_dir}"
80+
git push origin HEAD:"${BENCHMARK_DATA_BRANCH}"
81+
echo "deleted=true" >> "$GITHUB_OUTPUT"
82+
popd >/dev/null
83+
84+
- name: Build deployable site (main + PR previews)
85+
if: ${{ steps.cleanup_preview.outputs.deleted == 'true' }}
86+
env:
87+
GITHUB_REPOSITORY: ${{ github.repository }}
88+
run: |
89+
set -euo pipefail
90+
mkdir -p benchmark-history/runs
91+
python3 scripts/generate_pages.py \
92+
--history-root benchmark-history/runs \
93+
--output-dir site \
94+
--repository "${GITHUB_REPOSITORY}"
95+
96+
if [ -d benchmark-history/pr-previews ]; then
97+
mkdir -p site/pr-previews
98+
cp -R benchmark-history/pr-previews/. site/pr-previews/
99+
fi
100+
101+
- name: Configure Pages
102+
if: ${{ steps.cleanup_preview.outputs.deleted == 'true' }}
103+
uses: actions/configure-pages@v5
104+
105+
- name: Upload Pages artifact
106+
if: ${{ steps.cleanup_preview.outputs.deleted == 'true' }}
107+
uses: actions/upload-pages-artifact@v3
108+
with:
109+
path: site
110+
111+
- name: Deploy to GitHub Pages
112+
if: ${{ steps.cleanup_preview.outputs.deleted == 'true' }}
113+
uses: actions/deploy-pages@v4
114+
115+
- name: Add cleanup summary
116+
run: |
117+
{
118+
echo "### PR Preview Cleanup"
119+
echo "- PR: #${INPUT_PR_NUMBER}"
120+
if [ "${{ steps.cleanup_preview.outputs.deleted }}" = "true" ]; then
121+
echo "- Removed path: \`pr-previews/pr-${INPUT_PR_NUMBER}\`"
122+
echo "- URL invalidated: ${PR_PREVIEW_BASE_URL%/}/pr-${INPUT_PR_NUMBER}/latest/"
123+
else
124+
echo "- Nothing removed."
125+
fi
126+
} >> "$GITHUB_STEP_SUMMARY"

README.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,11 @@ Triggers:
192192
- On every pull request.
193193
- Manual `workflow_dispatch` with optional versions and tuning overrides.
194194
- Manual `workflow_dispatch` can also benchmark an immutable source snapshot by passing:
195-
- `sourceTarballUrl` (required for snapshot mode),
196-
- optional `sourceRepository`, `sourceSha`, `sourceRef`, `sourcePrNumber` for metadata.
195+
- `sourceRepository` + `sourceSha` (required for snapshot mode),
196+
- optional `sourceRef`, `sourcePrNumber`, `triggerRepository`, `triggerPrNumber`, `triggerPrUrl` for metadata and PR callback context.
197197

198198
Snapshot mode behavior:
199-
- Downloads the tarball snapshot and installs Javalin to Maven local from that source.
199+
- Clones `sourceRepository`, checks out `sourceSha`, and installs Javalin to Maven local from that source.
200200
- Detects `project.version` from the snapshot and adds it to the benchmark versions for the run.
201201

202202
Defaults:
@@ -206,5 +206,20 @@ Defaults:
206206
Output:
207207
- uploads raw benchmark JSON + generated trend report as workflow artifact,
208208
- adds a markdown benchmark summary table to the job summary.
209+
- publishes PR preview pages into the same GitHub Pages site under:
210+
- `/pr-previews/pr-<number>/latest/` (stable link),
211+
- `/pr-previews/pr-<number>/<run-id>/` (run-specific link).
212+
- keeps preview content in the `benchmark-data` branch under `pr-previews/` and deploys main + preview pages together.
213+
214+
Optional repository variables:
215+
- `BENCHMARK_DATA_BRANCH` (default `benchmark-data`)
216+
- `PR_PREVIEW_PAGES_BASE_URL` (default `https://javalin.github.io/javalin-performance-tests-testing/pr-previews`)
217+
218+
Cleanup:
219+
- Workflow `.github/workflows/cleanup-pr-preview.yml` deletes `pr-previews/pr-<number>/` from `benchmark-data`,
220+
then redeploys Pages so closed-PR previews disappear.
221+
- Intended to be dispatched from the source repository on `pull_request.closed`.
222+
223+
Old dedicated preview-repo model is no longer required.
209224

210225
The generated website also includes a plain-language “How To Read This” section.

0 commit comments

Comments
 (0)