vienalatina/.woodpecker.yml
Claude 24dbc9b961
Switch translation to OPUS-MT; mount models instead of baking them
M2M100 418M failed the quality gate on real articles. Measured on a 420-word
post: "frijoles" came back as "Beeren" (berries), "rompe la idea" as "breitet
die Idee" (spreads it — the opposite), "así sabe mi barrio" as "so weiß mein
Viertel" (knows, not tastes), and the opening sentence was not grammatical
German. Invented non-words throughout ("verforscht", "Treffenraum").

The pipeline itself was never at fault — masking held, structure survived,
zero placeholder failures across 14 files. The model was.

OPUS-MT is stronger on these specific pairs, and fits the existing CX22 with
no server upgrade, which was the constraint. Licence moves from MIT to
CC-BY-4.0, so attribution now ships with the platform.

Routes are verified against Hugging Face rather than assumed — the earlier
research could not reach HF, and half the names it guessed do not exist:

  es -> de       opus-mt-es-de           (small, ~74M)
  de -> es       opus-mt-tc-big-de-es    (tc-big, ~237M)
  es <-> pt-br   opus-mt-tc-big-itc-itc  (>>pob<< / >>spa<<)
  de <-> pt-br   no model in either direction — pivots through Spanish

Models now live at /srv/mt-models and are mounted read-only rather than baked
into the image. Model choice has needed iteration, and a directory swap beats
a 1GB image rebuild each time. It also keeps model conversion out of the image
build, which matters on a box that OOM-killed the last conversion.

MT_PROVIDER=m2m100 still selects the old engine.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NizVpJ2dwzCbjCrTLCjeHn
2026-09-18 12:41:45 +00:00

54 lines
1.9 KiB
YAML

# Woodpecker CI: translate → build → deploy
#
# Triggered by the Gitea push webhook. The translate step replaces the old
# synchronous WordPress save_post hook: publishing in Decap is one git commit,
# translation happens here, asynchronously, and every generated sibling lands
# as a reviewable bot commit.
#
# Translation is self-hosted — OPUS-MT runs on CPU inside the image, so there
# is no API key and no third-party request. Before the first run, on the server:
# bash scripts/fetch-models.sh # -> /srv/mt-models
# docker build -t vienalatina/translate:2 docker/translate
#
# The models are mounted rather than baked in, so swapping them later does not
# mean rebuilding the image. The repo must be marked "trusted" in Woodpecker
# for this mount, which it already is for the deploy step.
#
# Secrets to configure in Woodpecker (repo settings → secrets):
# gitea_push_token — Gitea token for the translations bot user
# (translations@vienalatina.com) with repo write access
#
# The deploy step writes to the Caddy web root via a host mount, which
# requires the repo to be marked "trusted" in Woodpecker.
when:
- event: push
branch: main
steps:
translate:
image: vienalatina/translate:2
pull: false # built locally on the server, never fetched from a registry
volumes:
- /srv/mt-models:/opt/mt/models:ro
environment:
GITEA_PUSH_TOKEN:
from_secret: gitea_push_token
commands:
- python scripts/translate.py
build:
image: hugomods/hugo:0.135.0
commands:
# Bundle Decap locally so the /admin page makes zero third-party requests.
- wget -q -O static/admin/decap-cms.js https://unpkg.com/decap-cms@^3.0.0/dist/decap-cms.js
- hugo --minify
deploy:
image: alpine:3.20
volumes:
- /var/www/vienalatina.com:/deploy-target
commands:
- apk add --no-cache rsync
- rsync -a --delete public/ /deploy-target/