\section{لماذا CI/CD مع LaTeX}
تعامل مع المستندات كما تتعامل مع الكود
تلتقط عمليات البناء الآلية الحزم المعطلة وأخطاء التجميع قبل أن تصل إلى المتعاونين أو المراجعين. وملفات PDF دائمًا على بُعد تشغيل واحد لخط المعالجة.
التقط الأخطاء قبل الدمج
تفشل فحوص خط المعالجة إذا تعذر تجميع المستند. يرى المراجعون كود LaTeX المعطل قبل وصوله إلى main.
مُخرَجات في كل تشغيل
يحفظ GitLab ملفات PDF المجمّعة كمُخرَجات للمهام. نزّل آخر بناء مباشرة من واجهة خط المعالجة.
لا حاجة إلى TeX Live محلي
يعدّل المساهمون ملفات .tex دون تثبيت توزيعة TeX Live بحجم 4 غيغابايت. يتم التجميع في السحابة.
\section{Prerequisites}
قبل أن تبدأ
- حساب FormaTeX (تعمل الخطة المجانية، 15 عملية تجميع شهريًا)
- مفتاح FormaTeX API من لوحة التحكم
- مستودع GitLab يحتوي على ملفات .tex
ضبط متغير CI/CD
في GitLab، انتقل إلى Settings › CI/CD › Variables › Add variable . اضبط المفتاح على FORMATEX_API_KEY، والصق مفتاح API كقيمة، وفعّل الخيار Masked حتى لا يظهر أبدًا في سجلات المهام.
\section{خط معالجة أساسي}
ملف .gitlab-ci.yml الأول لديك
ضع هذا الملف في جذر مستودعك. يسحب الصورة alpine:latest، ويثبّت curl وjq، ويجمّع main.tex، ويحفظ ملف PDF الناتج كمُخرَج في GitLab لمدة أسبوع.
# .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/api/v1/compile \
-H "X-API-Key: $FORMATEX_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"latex\": $(cat main.tex | jq -Rs .), \"engine\": \"pdflatex\"}" \
--output output.pdf
artifacts:
paths:
- output.pdf
expire_in: 1 week
only:
- main
- merge_requests\section{خط معالجة متقدم}
مراسي YAML والمهام المتوازية
وسّع النطاق إلى عدة مستندات دون تكرار نفسك. يستخدم خط المعالجة هذا مرساة YAML لتعريف قالب تجميع قابل لإعادة الاستخدام، ثم ينشئ منه نسخًا لـ main.tex وpresentation.tex بالتوازي. بعدها تنشر المهمة pages جميع ملفات PDF على GitLab Pages.
# .gitlab-ci.yml — advanced with matrix and error handling
stages:
- validate
- build
- publish
variables:
FORMATEX_API_URL: "https://api.formatex.io/api/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" \
-H "X-API-Key: $FORMATEX_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"latex\": $(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}
انشر ملفات PDF عبر GitLab Pages
تنسخ المهمة pages في خط المعالجة المتقدم جميع ملفات PDF المجمّعة إلى المجلد public/ وتعرضها كموقع GitLab Pages. وتصبح المستندات المجمّعة متاحة تلقائيًا على https://<group>.gitlab.io/<project>/ عند كل دفع إلى main. دون رفع يدوي ودون إعداد استضافة.
\section{Troubleshooting}
المشكلات الشائعة وحلولها
curl: command not found
لا تأتي صور Alpine مع curl افتراضيًا. أدرج دائمًا الأمر apk add --no-cache curl jq في before_script. وإذا انتقلت إلى صورة مبنية على Debian فاستخدم apt-get install -y curl jq بدلًا منه.
مفتاح API غير مُقنَّع في السجلات
تأكد من أنك أنشأت المتغير مع تفعيل الخيار Masked في GitLab Settings › CI/CD › Variables. بدون الإخفاء يظهر المفتاح كنص صريح في سجلات المهام. أعد إنشاء المتغير مع تفعيل Masked.
انتهاء مهلة ملفات .tex الكبيرة
The sync endpoint has a timeout for very large documents. For files over 10 MB, switch to the async endpoint (/api/v1/compile/async) which returns a job ID. Poll /api/v1/jobs/{id} until the status is completed, then download the PDF from /api/v1/jobs/{id}/pdf.
\section{تكاملات ذات صلة}
استخدم FormaTeX من أي بيئة
FormaTeX واجهة HTTP عادية. أمثلة جاهزة للنسخ واللصق لكل منصة رئيسية.

