\section{Why CI/CD for LaTeX}
Treat documents like code
Automated builds catch broken packages and compilation errors before they reach collaborators or reviewers. PDFs are always a pipeline run away.
Catch errors before merge
Pipeline checks fail if the document doesn't compile. Reviewers see broken LaTeX before it lands on main.
Artifacts on every run
GitLab stores compiled PDFs as job artifacts. Download the latest build directly from the pipeline UI.
No local TeX Live needed
Contributors edit .tex files without installing a 4 GB TeX Live distribution. Compilation happens in the cloud.
\section{Prerequisites}
Before you start
- FormaTeX account — free tier works (15 compilations/month)
- A FormaTeX API key from your dashboard
- A GitLab repository containing .tex files
Setting the CI/CD variable
In GitLab, go to Settings › CI/CD › Variables › Add variable. Set the key to FORMATEX_API_KEY, paste your API key as the value, and enable Masked so it never appears in job logs.
\section{Basic pipeline}
Your first .gitlab-ci.yml
Drop this file at the root of your repository. It pulls alpine:latest, installs curl and jq, compiles main.tex, and stores the resulting PDF as a GitLab artifact for one week.
# .gitlab-ci.yml
stages:
- build
compile-latex:
stage: build
image: alpine:latest
before_script:
- apk add --no-cache curl jq
script:
- |
curl -X POST https://api.formatex.io/v1/compile/sync \
-H "Authorization: Bearer $FORMATEX_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"source\": $(cat main.tex | jq -Rs .), \"engine\": \"pdflatex\"}" \
--output output.pdf
artifacts:
paths:
- output.pdf
expire_in: 1 week
only:
- main
- merge_requests\section{Advanced pipeline}
YAML anchors and parallel jobs
Scale to multiple documents without repeating yourself. This pipeline uses a YAML anchor to define a reusable compile template, then instantiates it formain.texandpresentation.texin parallel. The pages job then publishes all PDFs to GitLab Pages.
# .gitlab-ci.yml — advanced with matrix and error handling
stages:
- validate
- build
- publish
variables:
FORMATEX_API_URL: "https://api.formatex.io/v1"
.compile-template: &compile
image: alpine:latest
before_script:
- apk add --no-cache curl jq
script:
- |
RESPONSE=$(curl -s -w "\n%{http_code}" \
-X POST "$FORMATEX_API_URL/compile/sync" \
-H "Authorization: Bearer $FORMATEX_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"source\": $(cat $TEX_FILE | jq -Rs .), \"engine\": \"$ENGINE\"}")
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
if [ "$HTTP_CODE" != "200" ]; then
echo "Error: $(echo "$RESPONSE" | head -n-1)"
exit 1
fi
echo "$RESPONSE" | head -n-1 > "$OUTPUT_FILE"
artifacts:
paths:
- "*.pdf"
expire_in: 30 days
compile-main:
<<: *compile
stage: build
variables:
TEX_FILE: main.tex
ENGINE: pdflatex
OUTPUT_FILE: main.pdf
compile-presentation:
<<: *compile
stage: build
variables:
TEX_FILE: presentation.tex
ENGINE: xelatex
OUTPUT_FILE: presentation.pdf
pages:
stage: publish
script:
- mkdir -p public
- cp *.pdf public/
artifacts:
paths:
- public
only:
- main\section{GitLab Pages}
Publish PDFs via GitLab Pages
The pages job in the advanced pipeline copies all compiled PDFs into the public/ directory and exposes them as a GitLab Pages site. The compiled documents are then available at https://<group>.gitlab.io/<project>/ automatically on every push to main. No manual uploads, no hosting setup.
\section{Troubleshooting}
Common issues and solutions
curl: command not found
Alpine images ship without curl by default. Always include apk add --no-cache curl jq in your before_script. If you switch to a Debian-based image, use apt-get install -y curl jq instead.
API key not masked in logs
Make sure you created the variable with the Masked option enabled in GitLab Settings › CI/CD › Variables. Without masking, the key appears in plain text in job logs. Re-create the variable with Masked enabled.
Large .tex files timing out
The sync endpoint has a timeout for very large documents. For files over 10 MB, switch to the async endpoint (/v1/compile/async) which returns a job ID. Poll /v1/jobs/{id} until the status is complete, then download the PDF.
\section{Related integrations}
Use FormaTeX from any environment
FormaTeX is a plain HTTP API. Copy-paste examples for every major platform.

