ci(book): Eisvogel 3.5.1 for pandoc 3.6.1, and let the workflow test itself - #135
Kartikey1306 wants to merge 11 commits into
Conversation
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
srpatcha
left a comment
There was a problem hiding this comment.
Review — eBoot#135 "ci(book): Eisvogel 3.5.1 for pandoc 3.6.1, and let the workflow test itself"
head: d42fa57 author: Kartikey1306 ci: fail — Build PDF red, 25 green (Attach PDF to Release, Create GitHub Release, Update Dev PDF, assign skipped)
Verdict: First look. The diagnosis is right, the change is a real step forward, and the body is
honest about what it had not yet proved — it says the PDF build was NOT RUN and promises to cite
the run or say what it failed on. That run has now happened and nobody has reported it, so here it
is: the template bump works and the build still fails. The \chead already defined error is
gone; Build PDF now dies on ! LaTeX Error: File 'sourcesans.sty' not found. at the same exit 43.
The PR does not achieve what it sets out to do, and needs one more step before it is worth merging.
Separately, and this is the reason the workflow could stay red since April: no status check is
required to merge to master in this repository. I checked both the classic protection API and
rulesets.
Findings
| # | Severity | File:line | Finding | Recommended fix |
|---|---|---|---|---|
| 1 | High (P1) | .github/workflows/book-build.yml:101-123 |
Build PDF is still red on this PR's own head; Eisvogel 3.5.1 is necessary but not sufficient. Job 104160744680, run 34899177674, 2m40s: the template installs cleanly (Eisvogel 3.5.1 template installed, and the new cp Eisvogel-3.5.1/eisvogel.latex resolves, so the versioned-directory fix is correct), pandoc gets past the preamble, and then Error producing PDF. ! LaTeX Error: File 'sourcesans.sty' not found. → exit code 43. The failure moving is itself the evidence the bump worked — I read the log on #133, which carries the old 2.4.0 step, and it dies earlier with ! LaTeX Error: Command \chead already defined. at l.1560 ...nel@ifstar {\@dblarg\@@@chead}{\@chead}}. So this PR converted a template/pandoc incompatibility into a missing font dependency: Eisvogel 3.x pulls in a typeface the 2.4.0 template did not, and the install step's texlive-fonts-recommended/texlive-fonts-extra/texlive-latex-extra set does not supply this one. --pdf-engine=xelatex is used at :168 with no mainfont/monofont variable among the twenty -V flags at :175-194, so the template's default typeface is what gets loaded. |
Two ways, both one step: (a) install the style — add a diagnostic to the install step so the answer is recorded rather than guessed (kpsewhich sourcesans.sty || tlmgr search --global --file sourcesans.sty), then add the package it names to the apt-get install list; or (b) stop depending on it — pass -V mainfont=... and -V monofont=... naming fonts already in the image, which is the smaller diff and removes a dependency on a template default that can change again on the next bump. I would take (b) and pin the fonts explicitly, since the whole lesson of this PR is that the template's defaults are not a stable interface. Either way, the fix is not merged until the run is green — this PR's own body sets that standard and it should be held to it. |
| 2 | High (P1) — repo-level, pre-existing, not introduced by this PR | branch protection on embeddedos-org/eBoot@master |
No CI check is required to merge. Every one of the 26 checks on these PRs is advisory. GET /repos/embeddedos-org/eBoot/branches/master/protection returns required_pull_request_reviews (1 approval, dismiss-stale, require-last-push-approval), required_linear_history, required_conversation_resolution, allow_force_pushes: false — and no required_status_checks object at all. I checked the newer mechanism too, in case protection had been migrated: GET /repos/.../rules/branches/master returns exactly one rule type, copilot_code_review. So Build & Test (Linux x86_64), CodeQL, Host Build & Tests, Fuzz Harness Build and Build PDF can all be red and a PR still merges on one approval. This is the mechanism behind the very problem this PR fixes: gh run list --workflow book-build.yml shows 15 of 15 visible runs failure or cancelled, back through v1.4.0 and v1.5.0 in May 2026 — nothing ever had to stop, so nothing did. On a repository whose product is a bootloader, and in a batch that already contains a Critical finding (#129 finding 1, still open), a green wall that cannot block anything is worth more than a footnote. |
.ai/autoreview/apply-required-checks.sh already exists in this tree, which suggests the gap is known. Someone with admin should run it, or set required_status_checks.contexts to at least CI Gate, Host Build & Tests, Build & Test (Linux x86_64), Static Analysis (cppcheck + clang-tidy) and CodeQL. I did not run it: it mutates repository settings, which is outside what an unattended review should do on its own initiative, and choosing which contexts become blocking is a maintainer's call — Build PDF in particular should probably not be required until finding 1 is closed, or every PR in the repo goes red. |
What this PR gets right
Three things, and the third is the one I would keep even if the rest were rewritten.
The diagnosis is properly bounded. The body says "the LaTeX-level cause of the clash is not
established here — both templates use \chead*, and pandoc 3.6.1's own default template contains no
\chead — so I am not claiming a mechanism", and the step comment repeats it. That is §28's
evidence policy applied to a CI fix, and it is rarer than it should be. I verified the surrounding
factual claim independently: 15 of 15 visible book-build.yml runs are failure or cancelled,
including both May release tags.
The || true is gone. tar xzf Eisvogel-2.4.0.tar.gz 2>/dev/null || true was fail-open on
precisely the step that breaks — a missing or reshaped tarball failed silently and surfaced as a
confusing cp error one step later. Removing it is a strengthened check, the opposite of the
weakening .ai/reviewer.md asks reviewers to hunt for, and it is what turned the 3.x layout change
into a caught problem rather than a mystery.
Adding the workflow to its own paths: filter is the durable part. The job fired only on
docs/book/**, so a workflow-only change — this one included — could not be tested by the thing it
changes. It now can be, and the proof is finding 1: this PR's own run is what shows the fix is
incomplete. A change that makes its own inadequacy visible on the first try has earned its place
regardless of what happens to the other two lines.
Verification performed for this review
No local build: there is no pandoc, xelatex or TeX distribution on this host, so the PDF path cannot
be exercised here at all. Everything below is from the repository, the GitHub API, and the two
failing jobs' logs, read rather than summarised from the checks table. The user's eBoot checkout
was not touched; nothing was committed or pushed. This review covers a276016..d42fa573 (one commit,
one file); the rest of the bundle diff belongs to #115.
| Check | Result |
|---|---|
Build PDF on this head — log read (job 104160744680) |
Eisvogel 3.5.1 template installed ✅ → Error producing PDF. ! LaTeX Error: File 'sourcesans.sty' not found. → ##[error]Process completed with exit code 43. Finding 1. |
Build PDF on #133 — log read (job 104156749612, old 2.4.0 step) |
! LaTeX Error: Command \chead already defined. at l.1560 ...nel@ifstar {\@dblarg\@@@chead}{\@chead}}, exit 43. Confirms the two failures are different and the template bump advanced past the first. |
gh run list --workflow book-build.yml --limit 15 |
15/15 failure or cancelled — ci/book-pdf-eisvogel-3, build/security-options-wired-to-nothing, master (09-08), fix/eboot-test-issue ×5, v1.5.0 ×3, v1.4.0 ×3. The body's "no run has ever succeeded" is supported for every run still visible. |
GET /repos/embeddedos-org/eBoot/branches/master/protection |
no required_status_checks; 1 required approval, linear history, conversation resolution. Finding 2. |
GET /repos/embeddedos-org/eBoot/rules/branches/master |
one rule type only: copilot_code_review. Confirms finding 2 is not an artefact of protection having been migrated to rulesets. |
| Workflow diff read against the job's actual steps | EISVOGEL_VERSION: "3.5.1" reaches the step (it is echoed in the log's env block); cp Eisvogel-3.5.1/eisvogel.latex resolves; no || true remains on tar |
paths: filter, both triggers |
push.paths and pull_request.paths both now ['docs/book/**', '.github/workflows/book-build.yml']; push.tags: ['v*'], release.types and workflow_dispatch unchanged. The run existing at all is the practical proof. |
| pandoc invocation | --pdf-engine=xelatex at :168, --template=eisvogel at :170, twenty -V flags at :175-194, no mainfont or monofont — establishes finding 1's recommended fix (b) |
mergeStateStatus |
BLOCKED · reviewDecision: REVIEW_REQUIRED. Given finding 2, the block is the review requirement, not the red check. |
Architecture conformance
Conforms, and §21 is the only clause meaningfully engaged: eBoot is Tier 1 Foundation and
.github/workflows/ is Infrastructure within the owning repo, so §21.1 is not in play. §5.1
dependency direction is untouched — nothing compiles, links or ships differently. The design clauses
this PR sits against are §28 and §29. §29 lists the documentation architecture the book is part of,
and a book that has not built since 2026-04-25 means the Concepts, Guides and Operations
material §29 requires exists only as source. §28's evidence table is what the body honours by
refusing to claim a mechanism it had not established — and, applied to the PR itself, is what
finding 1 measures it against: the change is Planned until a green run makes it Implemented,
and it does not have one. Finding 2 sits against §28 more broadly: a status matrix and a CI wall are
both claims about a repository's state, and neither is worth anything if nothing enforces them.
Proposed changes
In this PR, before merge:
book-build.yml resolve the font dependency, then re-run and cite a green build-pdf:
(b) -V mainfont=... -V monofont=... naming fonts in the image, or
(a) kpsewhich sourcesans.sty || tlmgr search --global --file sourcesans.sty
in the install step, then add the package it names to apt-get
-> the body already sets "the run is the evidence"; hold to it (finding 1)
Repository setting, a maintainer's call, not this PR:
branch protection on master set required_status_checks.contexts, e.g. via the
existing .ai/autoreview/apply-required-checks.sh;
exclude Build PDF until finding 1 is closed (finding 2)
Noted by the author, worth not losing:
ebuild's book-build.yml carries the identical step and is red the same way;
whatever closes finding 1 should be ported there in the same week.
This branch is stacked on #115 and cannot land before it.
No fix PR opened. Finding 1 is High and the change is one line, which is the shape the brief
allows — but I cannot verify it. There is no pandoc, xelatex or TeX distribution on this host, so
fix-verify.sh could record nothing, and fix-submit.sh correctly refuses a PR with no recorded
verification. Guessing a font package name into a CI file and pushing it unverified is exactly the
failure mode this PR is fixing; the finding names the diagnostic that produces the right answer
instead. Finding 2 is a repository setting, not a diff.
Not checked
- The PDF build was NOT run, at all. No pandoc, no xelatex, no TeX on this host. Every statement
aboutBuild PDFcomes from the two jobs' logs. - Which package supplies
sourcesans.styis NOT established. I did not resolve it — no TeX
installation here to query and no network package index available in this run — which is why
finding 1's fix (a) is written as a diagnostic to run rather than a package name to add. Asserting
one would be a guess. - That fix (b) works is Inferred, not Verified. Eisvogel honours
mainfont/monofontand the
invocation sets neither, so overriding them should bypass the template default; I have not proved
that the 3.5.1 template has no other unconditional font\usepackage. - Runs older than the 15 listed were not examined — the author says their logs have expired and I
did not attempt to retrieve them. The claim "no run has ever succeeded" is Verified for everything
the API still returns. ebuild's copy of this workflow was not inspected. The body's claim that it carries the
identical step and is red the same way is taken on the author's word.eos's copy was not inspected either, so the body's explanation of why that repo is green is
unverified.- The #115 half of the bundle diff was not reviewed here. This review covers
a276016..d42fa573
only — one file. - The 25 green checks were not re-run and their logs were not read. In light of finding 2, note
that none of them would have blocked this PR even if they had been red.
Automated architecture review of d42fa5736845 — scheduled, model claude-opus-5, checked against the EmbeddedOS Master Design v2.0. Advisory only: this reviewer never approves, requests changes, or merges. Reply here to discuss or push back — a wrong finding is a bug worth reporting.
Twenty PRs were merged into master in ninety minutes on 09-07, each on the base it was written against. Master has not configured, compiled, linked or passed its tests since. Every nightly and every eos simulation run (which builds eBoot master) has been red for the same reason. Configure: - tests/CMakeLists.txt registered eboot_test_fdt_loader twice. embeddedos-org#84 added it, and embeddedos-org#85 -- stacked on embeddedos-org#84 -- re-added it at a different anchor when it was replayed onto a master that already had embeddedos-org#84. Same hunk as embeddedos-org#111. Compile (eboot_core): - embeddedos-org#55 restored a core/sha512.c from 02b7dac that keeps its byte count in ctx->count; the eos_sha512_ctx_t master ships has bitlen[2]/buffer_len (embeddedos-org#69/embeddedos-org#93). Back to the pre-embeddedos-org#55 file, blob-identical (d9aa57c). - embeddedos-org#55's source-list "correction" dropped core/boot_log.c, core/secure_boot.c and core/fdt_loader.c, which embeddedos-org#72/embeddedos-org#84 had added after embeddedos-org#55 was written. CMakeLists.txt is blob-identical to pre-embeddedos-org#55 again (f8fe6eb). - embeddedos-org#55 replaced the eos_boot_log_get_head() declaration with a second copy of eos_boot_log_read(); embeddedos-org#91 had already fixed the prototype it meant to fix. Header restored (964ebb8). - embeddedos-org#94 and embeddedos-org#105 each repaired the Ed25519 verifier and each added an identical static scalarbase(); both merged. One copy removed. - The same pair each added k_low_order[]/messages[] to test_ed25519.c. The embeddedos-org#105 copy is removed; embeddedos-org#94's stays because it also carries k_non_canonical[]. Tests that stopped passing because two merged PRs disagree on behaviour: - embeddedos-org#104 verifies the image signature at install unconditionally, before the anti-rollback check embeddedos-org#103 added, so embeddedos-org#103's unsigned images are refused as EOS_ERR_SIGNATURE before they can be refused as EOS_ERR_ANTI_ROLLBACK, and test_fw_transport's XMODEM install can no longer finalize. Both suites now stream genuinely signed images. eBoot has no Ed25519 signer in C, so tools/gen_fw_update_test_sigs.py signs the exact header prefixes those suites build under the RFC 8032 section 7.1 TEST 1 key and emits tests/vectors/fw_update_test_sigs.h; the suites serve that key from a simulated OTP slot 0. Negative control: one flipped signature byte fails test_write_streams_tlv_then_finalize_rejects_below_floor with EOS_ERR_SIGNATURE. - embeddedos-org#103's step 5b reads the TLV counter through the HAL slot containing the image; test_secure_boot_policy (embeddedos-org#82) declared no slots, so eos_secure_boot() returned EOS_SBOOT_ERR_BAD_HEADER two steps before the one under test. The fixture now places its image in slot A. Guards from embeddedos-org#95 that later merges walked back, never run until now because the C configure step failed first: - embeddedos-org#103 replayed the hand-written Valgrind foreach over the derived one. Restored foreach(TEST_NAME ${EBLDR_UNIT_TESTS}); eleven registered suites had no list(APPEND ...) and so no Valgrind run. - Seven suites assign tests_run = <literal> and their TEST() does not count; four suites have no TEST() macro at all. Counted, and classified. - embeddedos-org#101 added fuzz-build after embeddedos-org#90's gate; the gate did not wait for it. CI plumbing: - eosim-sanity.yml: the install-validate job is written in bash but ran under PowerShell on the Windows legs (no shell:), where SITE_PACKAGES=$(...) is an unknown command and `|| { exit 1 }` is an unexecuted script block. - scorecard.yml: ossf/scorecard-action@v2.4.0 pulls gcr.io, which now demands GCP billing. v2.4.3 pulls ghcr.io; eos already pins it and is green. Verified locally (macOS, clang): Release build clean, 31/31 ctest; the same under -DEBLDR_SANITIZE=ON (ASan+UBSan); 78/78 pytest. Not fixed here, reported separately: core/keystore.c's compiled-in default_dev_key is described as the RFC 8032 TEST 1 public key but differs from byte 21 on and is not a point on the curve, so nothing can verify against it on any board without OTP. With embeddedos-org#104 that makes firmware update refuse every image on such boards.
… -1.0.0 as an option test_out_of_range_version_is_rejected[-1.0.0] passed locally (Python 3.14) and failed in CI (ubuntu-22.04, Python 3.10) with argparse's own "expected one argument": the older negative-number matcher does not accept -1.0.0, so the token was read as an unknown option and imgpack.py's range check -- the thing under test -- never ran. The joined form is unambiguous on every interpreter and the test now reaches the tool's message.
tests/vectors/fw_update_test_sigs.h is the output of tools/gen_fw_update_test_sigs.py, committed because eBoot has no Ed25519 signer in C. Nothing checked that the two agree: a generator edit without a regeneration leaves test_fw_update and test_fw_transport verifying against stale signatures, failing with EOS_ERR_SIGNATURE and nothing to say why. tests/unit/test_fw_update_test_sigs.py runs the generator with the test's own interpreter and compares its stdout to the committed header byte for byte, so a line-ending change counts too. It follows the same dependency rule as test_eos_sign_payload_offset.py: with EOS_REQUIRE_SIGNING_TESTS set (the CI workflow sets it before the pytest step) a missing cryptography module fails the job instead of skipping. Negative control: one flipped hex byte in the header fails the test with a unified diff naming the line. build_image() and build_container() now carry a comment naming the coupling: the signed prefix is assembled both there and in the generator, and changing any field in it means changing the generator's copy and regenerating the header.
…epair embeddedos-org#103 and embeddedos-org#104 were both merged and disagree on whether the anti-rollback counter or the signature is checked first in eos_fw_update_finalize(). The master design orders boot as verify image, then version policy (section 8.1), but its update flow (section 15) never places the anti-rollback check, so the order the install path uses existed only in a PR body. ADR-020 records it: the signature over the signed header prefix is verified first, the TLV counter is read only after the prefix that binds it is authenticated, and an image that fails verification is refused as EOS_ERR_SIGNATURE without its counter being consulted. docs/adr/README.md is added in the shape of the eos repository's index; 020 avoids reusing 001 through 019. CHANGELOG.md gains the Unreleased entries for the repair: the configure, compile and link breakage after the 09-07 batch merge, the settled check ordering with the suites streaming signed images, the re-derived Valgrind list, fuzz-build in the CI gate, counted tests_run, the EoSim Windows legs running under bash, and the Scorecard action on its ghcr.io-hosted release.
The changelog said eleven suites had no Valgrind run. Eleven were missing from EBLDR_UNIT_TESTS, but four of those were named in the hand-written foreach and did run; seven had no run at all. Say which. ADR-020: its design-document citation now says where it comes from (the architecture review of embeddedos-org#115), and the sentence about the two PRs' bases is replaced with what the history shows -- embeddedos-org#103's commits predate embeddedos-org#104's merge, and embeddedos-org#104 was written without embeddedos-org#103's check in place.
The regeneration test's failure path -- the unified diff under the regenerate command -- ran only when the header was stale, so a green run never executed it and the coverage report said so. The report is now a helper the match asserts with, and a second test drives the helper with two byte strings that differ in one byte and checks the command and both sides of the changed line appear.
…itself No run of "Build & Release Book PDF" in this repository's history has succeeded: every run since the step was added (ef0dc50, 2026-04-25) is a failure, and every one whose log is still readable dies with ! LaTeX Error: Command \chead already defined. (exit 43) The workflow installs pandoc 3.6.1 from the release .deb and Eisvogel 2.4.0, which predates pandoc 3.6. The 3.x line merges pandoc's default template through 3.6.1 and later (its CHANGELOG names each merge) and states pandoc 3 compatibility. The LaTeX-level cause of the clash is not established here; the run on this change is what shows whether the pair works. Three changes to the one step and its trigger: Eisvogel 2.4.0 -> 3.5.1, as EISVOGEL_VERSION next to PANDOC_VERSION. The 3.x tarball extracts into Eisvogel-<v>/ rather than flat, so the copy names the directory -- a bare version bump would have failed at the cp. Ran the new step verbatim against the real release: template installed, 29,929 bytes; the old cp against the 3.x layout fails as predicted. No more `tar xzf ... 2>/dev/null || true`. That was fail-open on the exact step that breaks: a missing or reshaped tarball failed silently and the diagnostic landed on the cp after it. The workflow is added to its own paths: filter, for push and pull_request. It fired only on docs/book/**, so a workflow-only change could not get the run that proves it -- including this one. Verified: parsed structure asserted, not parse success -- both paths lists, push.tags ['v*'], branches, release types, workflow_dispatch and the job list are unchanged apart from the two added path entries; the template step contains no '|| true'. NOT RUN here: the PDF itself (no xelatex on this host). The evidence is this PR's own run of the job, cited in the PR once it exists -- and only if build-pdf ran rather than being skipped on has_book. Closes embeddedos-org#134
…ships
The first run of this change got past the template clash -- no more
"\chead already defined" -- and failed on the next thing:
! LaTeX Error: File `sourcesans.sty' not found. (exit 43)
Eisvogel 3.5.0 migrated its default font from the `sourcesanspro` package
to `sourcesans` (its CHANGELOG, 2026-06-28), and ubuntu-22.04's TeX Live
2021 has no sourcesans.sty. 3.4.0 is the last release on sourcesanspro,
which texlive-fonts-extra ships (checked against the package's file list),
and it already carries pandoc's default template merged through 3.9.
Install step re-run verbatim against the 3.4.0 release: template installed.
The PDF is still NOT RUN here; the PR's next run is the evidence.
The second run of this PR, on Eisvogel 3.4.0, failed exactly as master
does -- "Command \chead already defined" -- which means the first run's
apparent progress was an illusion: on 3.5.1 LaTeX died earlier, on a
missing font at line ~672 of the template, before it ever reached the
header setup at ~890. The clash was never in the Eisvogel version.
It is in this workflow. The pandoc step injected, through header-includes,
\usepackage{fancyhdr} \pagestyle{fancy} \fancyhead[L]{...} ...
and Eisvogel builds its own header and footer with KOMA's scrlayer-scrpage,
which defines \chead. The template places $header-includes$ (line 541)
before its header block (~890), so fancyhdr defined \chead first and
scrlayer-scrpage's \newcommand failed. Two header packages, one command.
Both arrived in ef0dc50 (2026-04-25), which is why no run of this job has
ever succeeded, on any pandoc or Eisvogel version.
The header and footer now go through the template's own variables --
header-left=\leftmark, header-right=<version>, footer-center=<press line>,
footer-right left at the template's default page number -- and the
fancyhdr block is gone. The rest of header-includes (float, booktabs,
longtable, caption, graphicx) is unchanged. Eisvogel stays at 3.4.0 for
the fonts (3.5.x needs sourcesans.sty, absent from TeX Live 2021).
Asserted on the parsed workflow: no fancyhdr/fancyhead/pagestyle{fancy}/
*rulewidth on any non-comment line of the step; the four variables and
the remaining header-includes packages present; no comment or blank line
inside the backslash-continued pandoc command (a first draft put the
explanation inside it, where '#' would have swallowed the continuation);
trigger paths, tags and EISVOGEL_VERSION unchanged.
Still NOT RUN here: the PDF. Third run is the evidence.
Run 3 got through the preamble and died on content:
! Misplaced alignment tab character &.
<argument> Srikanth Patchava & EmbeddedOS Contributors
The pandoc step passed -V "author=Srikanth Patchava & EmbeddedOS
Contributors". A -V value is inserted into the LaTeX verbatim, so the '&'
reached xelatex as an alignment tab. book.md's front matter already
declares the same author, and metadata goes through pandoc's writer, which
escapes it. The override is removed; the metadata is the one source.
Earlier runs never reached this line -- they died in the preamble first,
on \chead and on the font -- which is the same lesson as before: the first
error hides every later one.
Asserted on the parsed step: no -V author; every remaining literal -V value
is free of unescaped LaTeX specials (& % # _ ^ ~); header-includes is
exempt by design and values expanded at run time (title, version, date)
come from metadata or `date`, which carry none.
Still NOT RUN here. Fourth run is the evidence.
5e4a84c to
358009e
Compare
The comment said the missing sourcesans.sty was ubuntu-22.04's TeX Live 2021. The job runs on ubuntu-latest, which the green run at 358009e shows is ubuntu-24.04 (noble). The fact that matters -- the runner's texlive-fonts-extra has no sourcesans.sty, so Eisvogel 3.5.x cannot be used -- is unchanged and is what run 1 proved; the distro and TeX Live version I attached to it were assumed, not read from the log.
|
Green, twice, with
These are the first successful runs of this job in the repository's history. What it took, in the order the runs revealed it — each run removed one defect and exposed the next behind it, which is also why the PR opened with the wrong diagnosis:
Also in the diff: Corrections to earlier text on this PR, left visible: the body originally said run 1 showed "the template clash is gone" — it showed nothing of the kind; LaTeX had died on the font before reaching the header block. And "ubuntu-22.04 / TeX Live 2021" was assumed, not read. Stacked on #115 ( |
Closes #134
Problem
No run of
Build & Release Book PDFin this repository's history has succeeded — every run since the step was added (ef0dc50, 2026-04-25) isfailureorcancelled, from the May release runs (1bc7641,fa2b3b1) tomaster84bbef0on 09-08. Older logs have expired; every readable one dies with:The workflow installs pandoc 3.6.1 from the release
.deband Eisvogel 2.4.0, which predates pandoc 3.6. The 3.x line merges pandoc's default template through 3.6.1 and later (its CHANGELOG names each merge) and states pandoc 3 compatibility. The LaTeX-level cause was not known when this PR was opened; run 2 established it (see Verification) — it is this workflow's ownheader-includes, not the template version.Change
-V "author=Srikanth Patchava & EmbeddedOS Contributors"override is removed — a-Vvalue reaches LaTeX unescaped and&is an alignment tab; the identical author inbook.md's front matter is escaped by pandoc and is now the one source.fancyhdrheader block is removed; header and footer go through Eisvogel'sheader-left,header-rightandfooter-centervariables (page number is the template's default). This is the fix.EISVOGEL_VERSIONbesidePANDOC_VERSION. The 3.x tarball extracts intoEisvogel-<v>/, not flat, so the copy names the directory — a bare version bump would have failed at thecp. Why 3.4.0 and not 3.5.1: the first run of this PR pinned 3.5.1 and got past the template clash —\chead already definedwas gone — then failed onFilesourcesans.sty' not found. Eisvogel 3.5.0 (2026-06-28) migrated its default font from thesourcesanspropackage tosourcesans, which the runner'stexlive-fonts-extra(ubuntu-latest, 24.04 per the run log) does not ship. 3.4.0 is the last release onsourcesanspro(present intexlive-fonts-extra`, checked against the package's file list) and already carries pandoc's default template merged through 3.9.tar xzf … 2>/dev/null || true. That was fail-open on the exact step that breaks: a missing or reshaped tarball failed silently and the diagnostic landed on thecpafter it.paths:filter forpushandpull_request. It fired only ondocs/book/**, so a workflow-only change — this one included — could not get the run that proves it.Verification
Run 1 (
d42fa57, Eisvogel 3.5.1):Build PDF❌ —sourcesans.stynot found (line ~672 of the template; 3.5.x needs a font package TeX Live 2021 lacks).Run 2 (
4be6d7b, Eisvogel 3.4.0):Build PDF❌ —\chead already defined, exactly as master. (Correction to an earlier version of this body, which said run 1 showed "the template clash is gone": it showed no such thing — LaTeX had died on the font before ever reaching the header block at ~890.)What run 2 established: the clash is not in the Eisvogel version at all. This workflow injects
\usepackage{fancyhdr}+\fancyhead/\fancyfootthroughheader-includes, and Eisvogel builds its own header with KOMA'sscrlayer-scrpage, which defines\chead. The template places$header-includes$(line 541) before its header block (~890), so fancyhdr defines\cheadfirst andscrlayer-scrpage's\newcommandfails. Two header packages, one command — both arrived inef0dc50, which is why no run ever passed on any pandoc/Eisvogel pair.Run 3 (
5e4a84c): the fancyhdr block gone, header/footer through the template's own variables.Build PDF❌ — but a different error, six seconds in, past the whole preamble:Misplaced alignment tab character &inSrikanth Patchava & EmbeddedOS Contributors. The step passed-V "author=…"raw, and a-Vvalue is inserted into the LaTeX verbatim;book.md's metadata already carries the same author and is escaped by pandoc. Earlier runs never reached this line.Run 4 (
358009e): the-V authoroverride removed.Build PDF✅ — the first successful run in this job's history (run 34937342076):Validate Book Source,Build PDF,Verify PDF—eBoot-guide.pdf (760K, 48 pages, 777012 bytes)— andUpload PDF artifactall success;build-pdfran, it was not skipped onhas_book.Run 5 (
abf0522, the head): one comment line corrected — run 4's log showsImage: ubuntu-24.04, not the 22.04 / TeX Live 2021 I had written. ✅ again: run 34937741463,eBoot-guide.pdf (760K, 48 pages, 777043 bytes).Not run locally: the PDF itself — no
xelatexon this host. The evidence is the two green runs above, on358009eand on the headabf0522, withbuild-pdfexecuted (not skipped) in both.Elsewhere
ebuildcarries the identical step (book-build.yml:100) and is red the same way; the port waits for this run.eosis green only because its copy installs apt's pandoc 2.9 and no Eisvogel at all — itsPANDOC_VERSIONis dead — so it is not evidence for any pair. eBoot #133 is currently the only open PR that triggers this job; itsBuild PDFred is this defect, inherited.