Skip to content

ci(translate-changelog): verify the translation instead of trusting it - #109

Open
duckhawk wants to merge 1 commit into
v16.0from
fix/translate-changelog-retries
Open

ci(translate-changelog): verify the translation instead of trusting it#109
duckhawk wants to merge 1 commit into
v16.0from
fix/translate-changelog-retries

Conversation

@duckhawk

Copy link
Copy Markdown
Member

Description

Makes templates/Translate_Changelog.gitlab-ci.yml verify its own output instead of
trusting the translator:

  • every line is retried up to three times with a backoff, and a result that still holds
    Cyrillic counts as a failure exactly like an exception does;
  • if any line is still untranslated after the retries, the job fails and commits nothing;
  • an existing CHANGELOG/<ver>.yml is left alone when it holds no Cyrillic (a good or
    hand-written translation) and regenerated when it does;
  • the push rebases onto the remote branch first, so re-running the job is a no-op instead
    of a non-fast-forward failure;
  • the files to translate come from the diff of the last commit instead of "whatever
    v*.ru.yml has the highest version in the directory".

Why do we need it, and what problem does it solve?

deep_translator returns the source string on some backend failures instead of raising,
and the job swallowed that: one attempt per line, except Exception: translated = content,
exit 0. So the "English" changelog could ship Russian text under an English Changes:
header, with a green pipeline and an auto-created MR.

That is not theoretical. In the last batch of 15 storage-module changelogs (2026-08-20)
34 of 49 bullets stayed Russian; only the two modules whose bullets happened to be
short (snapshot-controller, sds-elastic) came out fully English. Example of what got
committed and MR'd:

Changes:
  - Исправление: успешное монтирование больше не считается ошибкой — в образ добавлен /etc/mtab …
  - CVE fixes

Two more defects surfaced while trying to recover from it:

  • The English file was generated exactly once (if eng_path.exists(): sys.exit(0)), so
    fixing the .ru.yml afterwards never refreshed the .yml, and the only hint in the log
    was the misleading No Russian changelog to translate (or English already exists).
  • Re-running the job could not push: the branch already carried the translate commit
    from the first run, so the retry died with ! [rejected] … (non-fast-forward).

What is the expected result?

A changelog branch either gets a fully English .yml or a red translate-changelog job
that names the lines it could not translate — never a silently half-Russian release
changelog. Re-running the job on a branch that already has the translation is a no-op, and
a hand-written .yml is never clobbered.

Verified against a stub backend (no network): flaky-then-ok retries produce a clean file; an
existing clean .yml is untouched; a Cyrillic-tainted .yml is regenerated; a backend that
never translates exits 1 without committing; empty stdin still falls back to the directory
glob. The template is also YAML-valid (yaml.safe_load) and the inline Python compiles
(py_compile).

Checklist

  • The code is covered by unit tests.
  • e2e tests passed.
  • Documentation updated according to the changes.
  • Changes were tested in the Kubernetes cluster manually.

deep_translator returns the source string on some backend failures instead of
raising, and the job swallowed that: every line got one attempt, an exception or
a silent passthrough fell back to the Russian text, and the job still exited 0.
The result shipped release changelogs that say 'Changes:' and then list them in
Russian -- 34 of 49 bullets in the last batch of 15 storage-module changelogs,
with only the modules whose bullets were short coming out fully English.

Now every line is retried up to three times with a backoff, a result that still
holds Cyrillic counts as a failure just like an exception, and if any line is
still untranslated the job fails and commits nothing. A red job is better than a
changelog nobody notices is in the wrong language.

Two more things the same failure exposed:

- The English file was generated once and never again ('if eng_path.exists():
  sys.exit(0)'), so editing the .ru.yml afterwards silently left the .yml stale,
  and the only hint was the misleading 'No Russian changelog to translate (or
  English already exists).' An existing .yml is now left alone when it holds no
  Cyrillic (a good or hand-written translation) and regenerated when it does.
- Re-running the job died with '! [rejected] ... (non-fast-forward)' because the
  branch already carried the translate commit from the first run. The push now
  rebases onto the remote branch first, which drops an identical commit as empty
  and makes the re-run a no-op.

The files to translate now come from the diff of the last commit (piped in on
stdin) instead of 'whatever v*.ru.yml has the highest version in the directory'.

Verified against a stub backend: flaky-then-ok retries produce a clean file, an
existing clean .yml is untouched, a Cyrillic-tainted .yml is regenerated, a
backend that never translates exits 1, and an empty stdin still falls back to
the directory glob.

Signed-off-by: v.oleynikov <vasily.oleynikov@flant.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant