[UPDATE] интеграция: безопасные маунты, кэш в tmpdir, только .tex/.pdf

This commit is contained in:
Arseny
2026-07-16 08:20:35 +03:00
parent 3a1acafc24
commit 08fc5d9aaa
4 changed files with 97 additions and 24 deletions
+1
View File
@@ -16,3 +16,4 @@ build/
# Report
report.md
output/
+4 -3
View File
@@ -20,8 +20,9 @@ RUN cd /tmp && \
fc-cache -f && \
rm -f /tmp/*.TTF /tmp/times32.exe
WORKDIR /app
WORKDIR /build
COPY . .
RUN uv sync --frozen --no-dev
RUN uv pip install --system --no-cache .
ENTRYPOINT ["uv", "run", "--no-dev", "md2gost"]
ENV UV_CACHE_DIR=/tmp/uv-cache
ENTRYPOINT ["md2gost"]
+59 -4
View File
@@ -4,12 +4,67 @@ set -euo pipefail
IMAGE="md2gost"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
usage() {
echo "Использование: md2gost file.md [-o dir]"
echo " file.md — исходный Markdown-файл"
echo " -o dir — выходная директория (по умолчанию ./build)"
exit 1
}
# Парсим аргументы
INPUT_FILE=""
OUTPUT_DIR="./build"
while [[ $# -gt 0 ]]; do
case "$1" in
-o)
OUTPUT_DIR="${2:-}"
[[ -z "$OUTPUT_DIR" ]] && usage
shift 2
;;
-h|--help)
usage
;;
-*)
echo "неизвестный флаг: $1" >&2
usage
;;
*)
INPUT_FILE="$1"
shift
;;
esac
done
[[ -z "$INPUT_FILE" ]] && usage
# Проверяем входной файл
if [[ ! -f "$INPUT_FILE" ]]; then
echo "ошибка: $INPUT_FILE не найден" >&2
exit 1
fi
# Абсолютные пути
INPUT_ABS="$(realpath "$INPUT_FILE")"
OUTPUT_ABS="$(realpath -m "$OUTPUT_DIR")"
mkdir -p "$OUTPUT_ABS"
INPUT_BASE="$(basename "$INPUT_FILE")"
# Собираем образ если нужно
if ! docker image inspect "$IMAGE" &>/dev/null; then
echo " образ $IMAGE не найден, собираю..."
echo "образ $IMAGE не найден, собираю..."
docker build -t "$IMAGE" "$SCRIPT_DIR"
fi
echo "→ конвертация $INPUT_FILE$OUTPUT_DIR/"
# Запуск контейнера:
# - вход: только .md файл (read-only)
# - выход: директория для .tex и .pdf
# - user: текущий пользователь (не root)
docker run --rm \
-e UV_CACHE_DIR=/tmp/uv-cache \
-v "$(pwd):/app" \
"$IMAGE" "$@"
-v "$INPUT_ABS:/input/$INPUT_BASE:ro" \
-v "$OUTPUT_ABS:/output" \
--user "$(id -u):$(id -g)" \
"$IMAGE" "/input/$INPUT_BASE" -o /output
+33 -17
View File
@@ -1,6 +1,8 @@
import argparse
import shutil
import subprocess
import sys
import tempfile
from pathlib import Path
from md2gost.parser import Parser
@@ -44,27 +46,41 @@ def main():
renderer = Renderer(parser.tokens, parser.front_matter)
latex = renderer.render()
tex_path = args.output / args.input.with_suffix(".tex").name
tex_path.write_text(latex, encoding="utf-8")
print(f"{tex_path}")
# Собираем во временную директорию, копируем только .tex и .pdf
with tempfile.TemporaryDirectory(prefix="md2gost-") as cache:
cache_dir = Path(cache)
if not args.no_pdf:
pdf_path = args.output / args.input.with_suffix(".pdf").name
log_path = args.output / "report.log"
# Генерируем .tex в кэш
tex_name = args.input.with_suffix(".tex").name
tex_path = cache_dir / tex_name
tex_path.write_text(latex, encoding="utf-8")
if not run_xelatex(tex_path, args.output):
print("ошибка: xelatex не собрал PDF", file=sys.stderr)
if log_path.exists():
for line in log_path.read_text(errors="replace").splitlines():
if line.startswith("!"):
print(f" {line}", file=sys.stderr)
sys.exit(1)
# Копируем .tex в выходную директорию
final_tex = args.output / tex_name
shutil.copy2(tex_path, final_tex)
print(f"{final_tex}")
if not run_xelatex(tex_path, args.output):
print("ошибка: xelatex (2-й проход) не собрал PDF", file=sys.stderr)
sys.exit(1)
if not args.no_pdf:
# Компилируем PDF в кэше (два прохода для TOC)
if not run_xelatex(tex_path, cache_dir):
print("ошибка: xelatex не собрал PDF", file=sys.stderr)
log_path = cache_dir / "report.log"
if log_path.exists():
for line in log_path.read_text(errors="replace").splitlines():
if line.startswith("!"):
print(f" {line}", file=sys.stderr)
sys.exit(1)
print(f"{pdf_path}")
if not run_xelatex(tex_path, cache_dir):
print("ошибка: xelatex (2-й проход) не собрал PDF", file=sys.stderr)
sys.exit(1)
# Копируем .pdf в выходную директорию
pdf_name = args.input.with_suffix(".pdf").name
pdf_path = cache_dir / pdf_name
final_pdf = args.output / pdf_name
shutil.copy2(pdf_path, final_pdf)
print(f"{final_pdf}")
if __name__ == "__main__":