Skip to content

fix(ci): install Julia + QuartoNotebookRunner in ci-benchmark - #328

Merged
ShixiangWang merged 3 commits into
mainfrom
ci/benchmark-julia-setup
Oct 11, 2026
Merged

ShixiangWang merged 3 commits into
mainfrom
ci/benchmark-julia-setup

Conversation

@ShixiangWang

@ShixiangWang ShixiangWang commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

Summary

Cold benchmark run 38109155362 (force_full_rebuild=true) failed at "Render website with Babelquarto" on [221/270] Julia/Heatmap.qmd:

Starting julia control server process. This might take a while...
Installing known registries into `~/.julia`
Error : incorrect library version (expecting : 1.5.7 ; actual : 1.5.5 )
ERROR: Ensuring an updated julia server environment failed

Root cause: ci-benchmark.yml had no Julia setup at all (its only Julia reference was the worker pre-render skip [[ "$rel" == Julia/* ]] && continue). With _freeze deleted by a cold run, Julia/*.qmd re-execute during the babelquarto render, and Quarto's julia-engine tried to bootstrap QuartoNotebookRunner at render time — which needs network + Pkg.update() and died.

Fix

Mirror the proven Julia setup from quarto-publish-update-cache.yml (in place on main since the Julia support PR):

  1. julia-actions/setup-julia@v3
  2. Cache ~/.julia keyed on Julia/Project.toml
  3. Pinned QuartoNotebookRunner env + QUARTO_JULIA_PROJECT export (skips Quarto's network-dependent ensureQuartoNotebookRunnerEnvironment)
  4. julia --project=Julia instantiate of the tutorial environment (CairoMakie, DataFrames, Statistics)

Two deliberate deviations:

  • actions/cache/restore instead of actions/cache — the benchmark must never save caches (workflow header: saving would pollute the shared freeze/julia pool with benchmark entries). Restore-only still lets warm benchmark runs reuse the shared ~/.julia cache.
  • Unconditional setup (no need_julia gate like quarto-publish.yml) — the benchmark has no changed-file detection step to feed such a gate, and a cold run always re-executes Julia qmds. On warm runs Julia setup costs ~1–2 min with the package cache restored; cold runs already cost 60+ min, so this is negligible.

Also re-ran a cold benchmark after the fix lands to validate the 677-package renv.lock cold path end-to-end (B1).

Test plan

  • workflow_dispatch cold benchmark (force_full_rebuild=true) on this branch: Julia/Heatmap.qmd renders via the pre-provisioned QNR env, no ensureQuartoNotebookRunnerEnvironment failure — run 38121976629, all steps green
  • Warm benchmark still passes (Julia setup skipped by cache hit, render uses freeze)
  • No cache is saved by the benchmark (restore-only semantics preserved)

🤖 Generated with Claude Code

Cold benchmark run 38109155362 (force_full_rebuild=true) failed at
"Render website with Babelquarto" on [221/270] Julia/Heatmap.qmd:
with _freeze deleted, Julia qmds re-execute and the julia-engine tried
to bootstrap its QuartoNotebookRunner server at render time, dying with
"ERROR: Ensuring an updated julia server environment failed" (after a
zstd library-version mismatch inside Pkg's registry setup).

The benchmark workflow had no Julia setup at all — its only Julia
reference was the worker pre-render skip. Mirror the proven setup from
quarto-publish-update-cache.yml: julia-actions/setup-julia, the pinned
QNR env (QUARTO_JULIA_PROJECT skips Quarto's network-dependent
ensureQuartoNotebookRunnerEnvironment at render time), and the Julia/
tutorial project instantiate.

Two deliberate deviations from the update-cache workflow:
- cache/restore instead of cache: the benchmark must never SAVE caches
  (its header says so — saving would pollute the shared pool); restore
  still lets warm benchmark runs reuse the shared ~/.julia cache.
- Julia setup is unconditional (no need_julia gate): the benchmark has
  no changed-file detection step to feed such a gate, and a cold run
  always re-executes Julia qmds.

Also clean up the phase marker: Julia setup time lands between
python_setup and pre_render marks, so "Pre-render non-frozen QMDs" in
the report absorbs it — acceptable for a manual-diagnostic workflow,
not worth extra clock entries.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ QMD Format Check

No new QMD tutorial files to check.

Automated check by the PR Review workflow.
See contribution guidance for the expected tutorial format.

Second validation run 38114723635 proved the Julia setup works (setup/
cache/install all green, zstd bootstrap error gone, QUARTO_JULIA_PROJECT
set) but babelquarto still failed at [221/270] Julia/Heatmap.qmd with
"ERROR: SyntaxError: Unexpected end of JSON input" from julia-engine's
JSON handshake with the QuartoNotebookRunner server
(writeJuliaCommand, julia-engine.js:1202).

Structural difference vs. the working quarto-publish-update-cache.yml:
the benchmark had no dedicated "Pre-render Julia notebooks" step, so
Julia qmds executed inline inside babelquarto's temp-dir render.

Port the proven pre-render step from update-cache: render Julia/*.qmd
before the parallel pre-render phase, with QUARTO_JULIA_PROJECT + TMPDIR
set and a julia_server_log tail on failure.  This freezes Julia outputs
into the workspace _freeze so babelquarto only pandoc-renders them.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ QMD Format Check

No new QMD tutorial files to check.

Automated check by the PR Review workflow.
See contribution guidance for the expected tutorial format.

Third validation run 38120426338 failed in the new pre-render step
itself: every Julia/Heatmap.qmd render died in under a second with
"NotFound: No such file or directory (os error 2): tmpdir" from
quarto's initSessionTempDir (makeTempDirSync).  The step sets
TMPDIR/TMP/TEMP=/mnt/TMP, but in ci-benchmark that directory was only
created later (in the R pre-render step's own mkdir); in
quarto-publish-update-cache.yml a dedicated "Create temporary
directory" step runs before the render pipeline.

Move that mkdir/chown step ahead of "Pre-render Julia notebooks".

Co-Authored-By: Claude Code <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ QMD Format Check

No new QMD tutorial files to check.

Automated check by the PR Review workflow.
See contribution guidance for the expected tutorial format.

@ShixiangWang

Copy link
Copy Markdown
Member Author

Validation — all green ✅

Cold benchmark run 38121976629: success (1 h 42 min total, force_full_rebuild=true).

Progression across the three validation runs:

Run Failure point Error
38109155362 (v0, no Julia setup) babelquarto [221/270] Julia/Heatmap.qmd incorrect library version (expecting 1.5.7; actual 1.5.5) → Ensuring an updated julia server environment failed
38114723635 (v1: Julia setup) babelquarto [221/270] Julia/Heatmap.qmd SyntaxError: Unexpected end of JSON input (julia-engine handshake, inline execution)
38120426338 (v2: + pre-render step) pre-render step itself NotFound: ... tmpdir — TMP_DIR never created
38121976629 (v3: + TMP_DIR mkdir) — all steps green

Final state: Set up Julia / Cache Julia packages / Install Julia packages / Pre-render Julia notebooks / Render website with Babelquarto / Write benchmark report / Upload benchmark report all success — Julia qmds now freeze before babelquarto, which renders them pandoc-only from _freeze (identical to the proven update-cache pattern).

Also verified: the regular PR checks (Github Page pull_request, Render the new Quarto files pull_request_target) are green on the final head.

@ShixiangWang
ShixiangWang merged commit 3276e33 into main Oct 11, 2026
5 checks passed
@ShixiangWang
ShixiangWang deleted the ci/benchmark-julia-setup branch October 11, 2026 09:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant