Skip to content

Commit 1138f1e

Browse files
committed
Step 2: Build the site in CI and publish it from main
The site job merges every job's results-* artifact and builds the site in the ruby_4.0 container, the same way the lint runs. It runs also when some benchmark jobs failed, so every PR gets a preview, and is skipped when the benchmark jobs did not run (a lint failure), so it adds no red check there. When a benchmark job failed, the build is marked incomplete and the page says a result shown as skipped may be a crash. The preview artifact is called site-preview, outside the results-* pattern, so a re-run of failed jobs never downloads it as results, and a re-run replaces the earlier preview. The run's Summary page links to it, so it is one click away, also on PRs from forks. Only a push to main where every benchmark job passed deploys to GitHub Pages, so a partial run never replaces the live site. Runs can finish out of order, so when main has moved on the deploy asks pick-benchmarks.sh whether the newer commits run benchmarks: if they do, their run deploys newer results and this one skips; if not (a README-only merge), this run's results are still the newest and it deploys. The deploy job is the only one with Pages permissions, and neither job is part of benchmarks-ok, so a Pages problem never blocks a merge.
1 parent e1e1426 commit 1138f1e

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

‎.github/workflows/benchmarks.yml‎

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,99 @@ jobs:
9999
path: results/
100100
if-no-files-found: warn
101101

102+
# Builds the results site from every job's results, also when some jobs
103+
# failed, so a PR gets a preview (the site-preview artifact, named outside
104+
# the results-* pattern so a re-run never downloads it). Skipped when the
105+
# benchmark jobs did not run (a lint failure). Only a push to
106+
# main where every job passed publishes it, so a partial run never replaces
107+
# the live site. Not required: a Pages problem never blocks a merge.
108+
site:
109+
needs: [changes, rake]
110+
if: ${{ !cancelled() && needs.changes.outputs.run == 'true' && needs.rake.result != 'skipped' }}
111+
runs-on: ubuntu-latest
112+
113+
steps:
114+
- uses: actions/checkout@v4
115+
- uses: actions/download-artifact@v4
116+
with:
117+
pattern: results-*
118+
path: results/
119+
merge-multiple: true
120+
- name: Build the results site
121+
# A failed benchmark job leaves no result file, like a benchmark that needs a newer Ruby, so the page says missing results may be crashes.
122+
env:
123+
RESULTS_INCOMPLETE: ${{ needs.rake.result != 'success' && '1' || '' }}
124+
run: docker compose run --rm -T -e RESULTS_INCOMPLETE --entrypoint ruby ruby_4.0 script/build_results_site.rb results _site
125+
- name: Upload the site preview
126+
id: preview
127+
uses: actions/upload-artifact@v4
128+
with:
129+
name: site-preview
130+
path: _site/
131+
# A re-run replaces the earlier attempt's preview.
132+
overwrite: true
133+
# A one-click link on the run's Summary page; it needs no extra permissions, so it works for PRs from forks too.
134+
- name: Link the site preview in the run summary
135+
env:
136+
PREVIEW_URL: ${{ steps.preview.outputs.artifact-url }}
137+
run: |
138+
{
139+
echo "### Results site preview"
140+
echo ""
141+
echo "[Download the site preview]($PREVIEW_URL) (a zip, needs a GitHub login), unzip it and open \`index.html\` in a browser."
142+
} >> "$GITHUB_STEP_SUMMARY"
143+
- name: Upload the site for GitHub Pages
144+
if: github.event_name == 'push' && github.ref_name == 'main' && needs.rake.result == 'success'
145+
uses: actions/upload-pages-artifact@v5
146+
with:
147+
path: _site/
148+
149+
deploy:
150+
needs: [rake, site]
151+
if: github.event_name == 'push' && github.ref_name == 'main' && needs.rake.result == 'success' && needs.site.result == 'success'
152+
runs-on: ubuntu-latest
153+
# Only this job can publish; the rest of the workflow keeps the default
154+
# token permissions.
155+
permissions:
156+
pages: write
157+
id-token: write
158+
environment:
159+
name: github-pages
160+
url: ${{ steps.deployment.outputs.page_url }}
161+
# One deploy at a time; a newer merge waits instead of cancelling one that
162+
# is halfway through.
163+
concurrency:
164+
group: pages
165+
cancel-in-progress: false
166+
167+
steps:
168+
# Runs can finish out of order, so an older run must not put its results back over a newer one.
169+
# When main moved on, ask pick-benchmarks.sh (the same rule CI uses) whether the newer commits run benchmarks.
170+
# If they do, their own run deploys newer results; if not (a README-only merge), this run's results are still the newest.
171+
- uses: actions/checkout@v4
172+
with:
173+
ref: main
174+
fetch-depth: 0
175+
- name: Check no newer run on main will deploy
176+
id: newest
177+
run: |
178+
if [ "$(git rev-parse HEAD)" = "$GITHUB_SHA" ]; then
179+
echo "deploy=true" >> "$GITHUB_OUTPUT"
180+
exit 0
181+
fi
182+
GITHUB_EVENT_NAME=push GITHUB_OUTPUT=newer.txt .github/scripts/pick-benchmarks.sh "$GITHUB_SHA"
183+
if grep -q '^run=true' newer.txt; then
184+
echo "main moved on and its newer commits run benchmarks, so their run deploys; skipping."
185+
echo "deploy=false" >> "$GITHUB_OUTPUT"
186+
else
187+
echo "main moved on, but nothing since this run affects benchmarks; deploying."
188+
echo "deploy=true" >> "$GITHUB_OUTPUT"
189+
fi
190+
- name: Deploy to GitHub Pages
191+
id: deployment
192+
if: steps.newest.outputs.deploy == 'true'
193+
uses: actions/deploy-pages@v5
194+
102195
# The check to require on main. Passes when every benchmark job passed, or
103196
# when there was nothing to benchmark.
104197
benchmarks-ok:

0 commit comments

Comments
 (0)