ci(book): Eisvogel 3.4.0, and stop defining \chead twice - #148
Kartikey1306 wants to merge 9 commits into
Conversation
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
Proven on this repository. The paths-filter change (item 5) fired this PR's own That is the first success in this job's history here — every prior run back to the 2026-05-28 tag build failed at The "NOT RUN here" in the body is now run: the PDF build itself is the evidence, on this repo's own runner, not inferred from eBoot. No further push planned; head stays |
CI -- ebuild has been red on master since the 09-08 batch merge, and the first failing step (ruff) has hidden the ones behind it. Lint (ruff, all nine Test legs): - test_build_dir_resolution.py imported shutil twice (F811). - test_package_recipe.py lost its trailing newline (W292). - test_ci_gate.py had `import itertools` / `import re` two hundred lines down (E402) -- my own embeddedos-org#103, replayed onto a file that had moved. These three hunks are byte-identical to embeddedos-org#122's, so either PR merging first leaves the other clean. Type check and tests (never reached on master since 09-08): - ebuild/packages/index_sync.py calls PackageRecipe.to_dict(), which embeddedos-org#111 defined and embeddedos-org#112 -- merged five minutes later from a base without it -- deleted in its replay. mypy names it once; pytest fails nine test_index_sync cases with AttributeError. The method is restored verbatim from embeddedos-org#111 (cc90078): it emits the `package:`/`build:` keys parse_recipe() reads back, which an asdict() replacement would not. Vendored core drift: - embeddedos-org#109 (dba3d83) edited core/eos/docs/three-way-alignment.md, a vendored copy pinned to eos 5544c98, so drift went 44 -> 45 and the guard failed as designed. Reverted to the pinned content (blob 7f9c8c1, the same bytes as eos:docs/three-way-alignment.md at the pin). The alignment note belongs in ebuild's own docs or upstream in eos, not in the snapshot. OSSF Scorecard: - ossf/scorecard-action@v2.4.0 pulls gcr.io/openssf/scorecard-action, and gcr.io now refuses the pull ("requires billing to be enabled"). v2.4.3 pulls from ghcr.io; eos already pins it and its Scorecard job is green. Not in this PR: EoSim Sanity's Windows/macOS legs install a wheel that has never been published; embeddedos-org#121 (srpatcha) already replaces that with the clone the other legs use. Verified locally: ruff clean, yamllint clean, mypy clean over 107 files, 680 passed / 1 skipped, scripts/check_vendor_drift.py 44/44 and 46/46.
…/3.11, yamllint on Windows Both surfaced on this branch's first CI run, once ruff let the job get past its first step. - ebuild/plugins/__init__.py: on Python 3.10 and 3.11 the stubs type entry_points() as the deprecated mapping, and its .get() wants an EntryPoints default, so mypy fails with arg-type. The line carried a '# type: ignore[attr-defined]' -- the wrong error code, so it suppressed nothing. Spelled out with a cast, byte-identical to embeddedos-org#122's hunk (54605f0). - .yamllint.yml: the Windows runners check out with core.autocrlf=true, so every YAML file arrives as CRLF and the default new-lines: unix rule rejected every line. The step was added on 09-03 and had never passed on that leg. new-lines: platform accepts the checkout's own convention.
…e checkout's line ending new-lines: platform was the wrong fix. The Windows runners' autocrlf turns LF files into CRLF -- except a file that already carries a stray CR, which git leaves alone, and auto-assign.yml had one on its last line. So under 'platform' Windows expected CRLF and got LF on that file's first line, and the leg was red again for the opposite reason. Pin *.yml and *.yaml to eol=lf so every OS lints the same bytes, keep yamllint's default unix rule, and drop the stray CR.
…h a round-trip test PackageRecipe.to_dict() was written before install_args existed and was never taught about it, so a recipe that went through index_sync came back from the cache with install_args empty while every other field survived. It also returned the recipe's own list objects, so a caller that appended to what it got back edited the recipe behind its back. install_args is now emitted after build_args, matching the order parse_recipe() reads them, and every list field is copied on the way out. index_sync's entry-to-recipe mapping carries install_args too; without that the field could not arrive from an index at all. The new round-trip test builds a recipe with every field set and asserts parse_recipe(safe_load(safe_dump(to_dict()))) equals it; against the previous to_dict() it fails on install_args. A second test checks the lists are copies, and test_index_sync gains a case that an index entry's install_args reaches the cached YAML.
actions/checkout, ossf/scorecard-action and codeql-action/upload-sarif were referenced by moving tags. A tag can be re-pointed; a commit cannot, and Scorecard itself flags unpinned actions. Each is now pinned to the commit its tag resolved to on 2026-09-14, with the tag kept in a trailing comment, the same shape linked-issue.yml already uses.
The changelog records what the master repair changed and why. CONTRIBUTING gains a note for Windows contributors: .gitattributes now pins YAML to LF, but the attribute governs future checkouts and commits, not files already in a working tree, so an existing clone needs one git add --renormalize . (or a fresh clone) before yamllint stops seeing CRLF.
…working tree git add --renormalize . re-applies the clean filter to the index; it never rewrites files, so a clone with CRLF YAML still has CRLF YAML afterwards (reproduced in a scratch clone with core.autocrlf=true: two CRs before, two after, status clean). What re-checks the files out is git rm --cached -r . && git reset --hard HEAD, or a fresh clone. CONTRIBUTING and the changelog now say that. The changelog entry also lists every file it describes and the plugins/__init__.py type-check fix it had left out, and the to_dict() comment no longer claims to follow parse_recipe()'s order.
The review at 43b0337 found the one-line assertion pinning install_args next to build_args and, six lines above it, recipe.py's docstring saying key order does not matter. Both are true: order is not a correctness property, because parse_recipe() reads every key by name, and it is a stability property, because index_sync writes the dict as cached YAML that humans diff. The assertion now says which of the two it is guarding and what to do when a reordering is deliberate, so a future failure reads as intentional rather than as a mystery. No behaviour change. ruff clean; pytest 683 passed, 1 skipped.
Build & Release Book PDF has never succeeded here. Every run back to the
2026-05-28 tag build dies with
! LaTeX Error: Command \chead already defined.
The workflow is byte-identical to eBoot's pre-fix copy, and eBoot#135
found the cause there, over three runs; this is that fix, ported unchanged.
The pandoc step injected \usepackage{fancyhdr} and \fancyhead/\fancyfoot
through header-includes. Eisvogel builds its headers with KOMA's
scrlayer-scrpage, which defines \chead, and $header-includes$ sits before
the template's own header block -- so fancyhdr defined \chead first and
the template's \newcommand failed. Both arrived in the same April commit,
which is why no Eisvogel or pandoc version ever made it green. Header and
footer now go through the template's own variables (header-left,
header-right, footer-center).
The -V author override is gone too: a -V value is verbatim LaTeX, and the
'&' in the author string is an alignment tab. The front matter in
docs/book/book.md carries the author and pandoc escapes metadata.
Eisvogel 2.4.0 -> 3.4.0: 2.4.0 predates pandoc 3.6; 3.5.x moved to
sourcesans.sty, which the runner's texlive-fonts-extra does not ship, so
3.4.0 is the last release that works. The 3.x tarball extracts into a
versioned directory, so the cp names it. tar no longer carries || true: a
bad tarball must fail at the step that broke, not at the cp after it.
The workflow is added to its own paths: filter, so this change gets the
run that proves it -- before, a workflow-only PR could not trigger the job.
Verified structurally on the parsed document, not by yaml.safe_load alone:
push.paths and pull_request.paths carry both entries, push.tags is still
['v*'], release.types unchanged, no non-comment line in the pandoc step
mentions fancyhdr, no continued line is followed by a comment. eBoot#135
is green twice at abf0522 (eBoot-guide.pdf, 48 pages).
Closes embeddedos-org#147.
2b4c426 to
4678981
Compare
|
Corrected the head. Verified at this head with CI's exact invocations: The Book PDF proof (run 34938663921, 37 pages) was at |
|
Re-proven at |
Closes #147.
Build & Release Book PDFhas never succeeded on this repository — every run back to the 2026-05-28 tag build dies at! LaTeX Error: Command \chead already defined.(exit 43). The workflow is byte-identical to eBoot's pre-fix copy (diffagainst eBoote152d8eis empty), and eBoot#135 diagnosed and fixed it there over three runs. This is that fix, ported unchanged.What was wrong — five things, one of which is the cause
\usepackage{fancyhdr}+\fancyhead/\fancyfootthroughheader-includes. Eisvogel builds its headers with KOMA'sscrlayer-scrpage, which defines\chead;$header-includes$sits before the template's own header block, sofancyhdrdefined\cheadfirst and the template's\newcommandfailed. Both arrived in the same April commit, so no Eisvogel/pandoc pair has ever produced a green run. Headers and footer now go through the template's own variables:-V header-left=\leftmark -V header-right=<version> -V footer-center=….-V "author=… & …"is verbatim LaTeX, and&is an alignment tab. Removed;docs/book/book.md:3carries the author in front matter, which pandoc escapes.EISVOGEL_VERSION. 2.4.0 predates pandoc 3.6. 3.5.x switched tosourcesans.sty, which the runner'stexlive-fonts-extradoes not ship (eBoot run 1 proved this) — 3.4.0 is the last release that works. The 3.x tarball extracts intoEisvogel-<v>/, so thecpnames it.tar xzf … 2>/dev/null || trueremoved. A bad tarball must fail at the step that broke, not at thecpafter it.paths:filter (push and pull_request), so this PR gets the run that proves it. Before, a workflow-only change could not trigger the job at all.eBoot's run 2 showed the version bump alone does not fix it — item 1 is load-bearing.
Verification
Structural, on the parsed document — not
yaml.safe_loadsucceeding, which proves only that it is YAML:push.paths == ['docs/book/**', '.github/workflows/book-build.yml'], same forpull_requestpush.tags == ['v*']— release trigger intactpush.branches,release.types,workflow_dispatchunchangedenv.EISVOGEL_VERSION == '3.4.0'fancyhdr/fancyhead/pagestyle{fancy}-V authoroverride remains\-continued line is followed by a comment or blank (which silently ends the command)|| true;cpnamesEisvogel-${EISVOGEL_VERSION}/jobsmapruff check .pytest tests/Build & Release Book PDFatabf0522eBoot-guide.pdf 48 pages— first green in that job's historymastercopy vs eBoot pre-fix copygit apply --checkof the eBoot diff against ebuildmasterNOT RUN here: the PDF build itself. It needs the runner's TeX Live; this PR's own
Build & Release Book PDFrun is the proof for this repository, and it will fire because of item 5.