minted package fails in CI when restricted shell-escape omits pygmentize
0 reputation · 16 Feb 2022, 12:24 UTC
0 reputation · 16 Feb 2022, 12:24 UTC
A LaTeX project uses the minted package for syntax highlighting. Locally the document compiles with --shell-escape enabled, but the production CI pipeline runs TeX Live with --shell-escape=restricted (the default on many hosted runners). The restricted whitelist in texmf.cnf (shell_escape_commands) does not include pygmentize or python3, so the build fails with “Package minted Error: You must invoke LaTeX with the -shell-escape flag.”
-shell-escape cannot be granted in the shared CI environment due to policy._minted-* cache directories is undesirable because Pygments versions differ between local machines and the CI container, risking stale or incompatible highlighted output.Find a reproducible, version-pinned workflow that allows minted to produce identical highlighted output in both environments without requiring full shell-escape or committing generated cache directories.
Which combination of minted package options (e.g., frozen, cachedir, outputdir) and CI-side preparation steps (pre-generating .pyg files, using a fixed Pygments Docker image) yields a portable, auditable build? Does pythontex in its two-pass mode avoid the whitelist limitation when Python is present but pygmentize is not whitelisted? What is the minimal TeX Live version where the restricted whitelist can be safely assumed to include repstopdf but not pygmentize?
Use minted with the frozen option and an explicit cachedir, then generate the .pyg cache files in a CI preparation step that runs pygmentize directly from the shell rather than through TeX's shell-escape mechanism. Pinning the Pygments version makes the output reproducible, and the frozen cache lets the actual LaTeX compile run without --shell-escape.
Likely explanation: The restricted shell_escape_commands whitelist omits pygmentize, so minted cannot invoke it at runtime and aborts with the -shell-escape error. Confirmed facts: minted calls pygmentize via the shell unless a frozen cache is present; the CI policy forbids full shell-escape; and the whitelist is fixed by the distribution image.
pip requirement.pygmentize for every code block and writes the results into the cache directory that minted expects.\usepackage[cachedir=minted-cache,frozen]{minted}. Add outputdir=build only if you compile with -output-directory.latexmk or pdflatex without --shell-escape. The frozen cache satisfies minted without any external calls.If pre-generating the cache inside the restricted runner is impractical, the fallback is to generate the cache once in a trusted environment with the same pinned Pygments version and publish it as a build artifact, but do not commit the _minted-* directory to source control.
Yes. In its normal two-pass workflow, pythontex is executed as a standalone script between LaTeX runs. Because the script is launched directly by the CI shell rather than by TeX's restricted shell-escape subsystem, the shell_escape_commands whitelist does not apply. pythontex also does not use pygmentize; it runs Python directly. The trade-off is that you must rewrite code blocks with pythontex commands instead of minted environments.
repstopdf has been present in the default restricted whitelist for many years, whereas pygmentize has never been included by default. The exact minimal TeX Live version is distribution-specific; verify it in your image rather than assuming a cutoff.
kpsewhich -var-value shell_escape_commandsAfter generating the cache, run the compile with -interaction=nonstopmode and confirm that no pygmentize process is spawned. A practical check is to compare the PDF checksum between a local full-shell-escape build and the CI frozen build; they should match when the Pygments version and style are identical.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.