LaTeX Builder
Build LaTeX documents with Git-based versioning and automatic diff generation.
Features
- Git integration — automatic version naming based on tags, commits, and dirty state
- LaTeX compilation — xelatex / pdflatex / lualatex with bibtex
- Diff generation — visual diffs between Git versions via latexdiff
- GitHub Action — use directly in CI/CD workflows
- CLI tool — installable via pip / uvx for local use
Use as a GitHub Action
- uses: wangyihang/latex-builder@v1
with:
tex-file: main.tex
Full example workflow
name: Build LaTeX
on:
push:
branches: [main]
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # needed for diff against previous tags
- uses: wangyihang/latex-builder@v1
id: latex
with:
tex-file: main.tex
compiler: xelatex
output-dir: output
- uses: actions/upload-artifact@v4
with:
name: latex-output
path: |
${{ steps.latex.outputs.pdf-path }}
${{ steps.latex.outputs.diff-pdf-path }}
${{ steps.latex.outputs.metadata-path }}
Inputs
| Input | Default | Description |
|---|---|---|
tex-file |
main.tex |
Main .tex file to compile |
compiler |
xelatex |
LaTeX compiler (xelatex, pdflatex, lualatex) |
compare-with |
(auto) | Git tag or commit to compare against |
output-dir |
output |
Directory for output files |
timeout |
300 |
Per-command timeout in seconds |
revision-file |
variables/revision.tex |
Path for generated revision.tex |
skip-diff |
false |
Build current version only |
diff-only |
false |
Generate diff .tex without building PDFs |
verbose |
false |
Enable debug logging |
texlive-packages |
(empty) | Extra TeXLive packages to install (space-separated) |
The Action uses a composite runner (not Docker), so TeXLive is installed on the GitHub-hosted runner and cached automatically between runs. First run takes ~2 minutes; subsequent runs with cache hit take ~10 seconds.
Outputs
| Output | Description |
|---|---|
version-name |
Generated version string (e.g. v1.2.3-abc1234-20240101120000) |
pdf-path |
Path to the current-version PDF |
diff-pdf-path |
Path to the diff PDF |
diff-tex-path |
Path to the diff .tex source |
metadata-path |
Path to metadata.json |
Use as a CLI tool
Install
pip install latex-builder
# or
uvx latex-builder --help
Commands
# Build and generate diffs (default)
latex-builder build
# Specify options
latex-builder build -f thesis.tex -c pdflatex -o dist --compare-with v1.0.0
# Build without diff
latex-builder build --skip-diff
# Generate diff .tex only (no PDF)
latex-builder build --diff-only
# Generate only revision.tex
latex-builder revision
Python API
from pathlib import Path
from latex_builder import Config, Compiler, GitRepo
from latex_builder.diff import build_and_diff
repo = GitRepo(Path("."))
current = repo.current_revision()
compare = repo.auto_compare_target()
cfg = Config(compiler=Compiler.XELATEX, output_dir=Path("output"))
build_and_diff(repo, current, compare, cfg)
Version naming
Follows GoReleaser-style naming:
| Scenario | Format | Example |
|---|---|---|
| Tagged commit | {tag}-{hash} |
v1.2.3-abc1234 |
| Untagged commit | {next}-snapshot-{hash} |
v1.2.4-snapshot-abc1234 |
| Dirty tree | adds -dirty |
v1.2.4-snapshot-abc1234-dirty |
Output files
{version}.pdf— current version PDF (e.g.v1.2.4-snapshot-abc1234.pdf)diff-{old_hash}-vs-{new_hash}.tex— diff LaTeX sourcediff-{old_hash}-vs-{new_hash}.pdf— diff PDFmetadata.json— build metadata (includes timestamps, full version names)revision.tex— LaTeX macros (\GitCommit,\GitTag,\GitBranch,\GitRevision,\CompiledDate)
Requirements
- Python 3.11+
- Git
- LaTeX (xelatex/pdflatex/lualatex + bibtex + latexdiff)
All dependencies are bundled in the Docker image / GitHub Action.
Project structure
latex_builder/
├── cli.py # click-based CLI
├── config.py # Config dataclass + Compiler enum
├── revision.py # Frozen Revision dataclass
├── git.py # Git operations
├── compiler.py # LaTeX compilation
├── diff.py # Diff orchestration
├── shell.py # Subprocess runner
└── log.py # Structured logging
Release files for latex-builder 0.0.16
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| latex_builder-0.0.16.tar.gz | 41.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| latex_builder-0.0.16-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 55.4 kB
Release files / latex_builder-0.0.16.tar.gz
| Download URL | latex_builder-0.0.16.tar.gz |
|---|---|
| Size | 41.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9f9e3d446df154b022891848bdb82003a4c1464111b01991aa5b06ed866b4aba
|
|
BLAKE2b-256 checksum How to use checksums |
79224b7d9a1a1308e62341e09e4826912e46cc87386b59e6083243672b79beb1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.4 {"installer":{"name":"uv","version":"0.11.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / latex_builder-0.0.16-py3-none-any.whl
| Download URL | latex_builder-0.0.16-py3-none-any.whl |
|---|---|
| Size | 14.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
af1c1c82f204fcdedfa8bc86268759a203d0721970f51348b1fbdfc04eeda8da
|
|
BLAKE2b-256 checksum How to use checksums |
34786510672c765078675966c4b388104328ec97aa64dd38a7e905a7c2c82a57
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.4 {"installer":{"name":"uv","version":"0.11.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|