Repository navigation
ci(translations): a content PR may delete locale siblings, never add or edit one - #292
Merged
Merged
Conversation
…ct adding or editing one The ownership gate read a `git diff --name-only` list, which names a deleted path exactly like an edited one. Once TRANSLATION_BOT_LOGIN is set, that rejects the retire/rename deletion AGENTS.md step 3 requires. The Ownership step now lists `git diff --name-status --no-renames`, and the gate reads each status. A human PR may delete a locale artifact, and an addition or modification still fails. A rename is the old path deleted plus the new path added, also when the list carries an R line, so a renamed translation still fails. The translation account's rule is unchanged, and it now also sees the source side of a rename. The gate gains a --self-test of 21 cases, each run through the real entry point with the variable set and unset, and the self-test runner lists it. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FeA1nwBz1ohH65dvffUGKr
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #291
The ownership gate read a
git diff --name-onlylist. That format names a deleted path exactly like an edited one, so onceTRANSLATION_BOT_LOGINis set the gate would reject the retire/rename deletion that AGENTS.md step 3 requires.With this PR, a non-translation-account PR may delete locale artifacts, and is still rejected if it adds or modifies one. The translation account's rule is unchanged.
What changed
.github/workflows/translations.ymlgit diff --name-status --no-renames "origin/${BASE_REF}...HEAD".--actor "$PR_AUTHOR" --files changed.txt.--name-onlylist (changed-output.txt), untouched..github/scripts/check-translation-ownership.mjsD. It fails on anyA,MorT.--name-only), an unknown status, and anR/Cline without two paths. If the workflow drifts back to--name-only, the gate goes red on the next PR, not on the day enforcement starts.--self-testwith 21 cases. Each case runs the real entry point with the workflow's argv twice: once with the variable set to a placeholder login, once unset.tools/ci-scripts/run-self-tests.mjspnpm turbo run testin the requiredbuildjob runs it.Rename: read as delete + add
The gate reads a rename as what it does to the tree: the old path is deleted and the new path is added.
--no-renames, so git writes a rename that way.R100 OLD NEWline. The gate expands it the same way.Cline counts as the new path added, with the source untouched.A renamed locale file still fails a human PR, because its new path is a translation added by hand. I measured both list forms,
--no-renamesand theRline. Both exit 1 and name only the new path.Why not treat a rename as a modification of both paths. The two readings disagree on one case: a locale file renamed to a non-locale path. With rename detection on, that verdict would also depend on git's ≥50% similarity guess. Delete + add is the only reading where the same tree change gets the same verdict whichever flags made the list.
Measured on d2944dc
TRANSLATION_BOT_LOGIN=placeholder-translator. The human actor isobjectstack-fleet[bot].git diff --name-status --no-renamesoutput.7612ffe...9c11af4, 14D✓ 14 file(s) changed: 14 translation artifact(s) deleted, none added or modified.This PR adds or modifies 2 translation artifact(s):This PR adds or modifies 1 translation artifact(s):, naming only the modified oneThis PR adds or modifies 1 translation artifact(s):, naming the new path✗ translation PRs may only touch translation artifacts.⚠ TRANSLATION_BOT_LOGIN is not set — ownership is not enforced yet.✓ 1 file(s) changed, no translation artifacts touched.For comparison, the same (a) run on main's gate exits 1: "This PR edits 14 translation artifact(s)".
(d) byte for byte. I compared main's gate fed the old
--name-onlylist against this gate fed the new list, with the variable unset. Output is identical on four diffs: PR #290, English-only, add+modify, and the translation-account diff.The only difference is on a diff that contains a rename. The count line now includes the rename's source path, so it reads 2 instead of 1.
--name-onlyused to hide that path.Ablation (one-off, not kept)
Run with objectstack's
scripts/ablation-replace.mjsin WRAP mode, against the committed tree. For each leg:2a4dd41changed;2a4dd41, andgit diff HEADis empty.The three legs:
writtencounts every locale path). Self-test exit 1 with 6 cases red, including PR docs: delete the 14 locale siblings that still forecast federation as unshipped #290's 14 siblings, a page retirement and a page rename.writtenalways empty). Exit 1 with 8 cases red: add, modify, meta, T, mixed, both rename forms, and C.Rexpansion drops the source path. Exit 1 with 1 case red: the translation account renaming English into a locale path.Gates on d2944dc
pnpm turbo run build --force --concurrency=2(os-verify-lock): VERDICT command-exit 0; Tasks 1 successful, 0 cached.pnpm turbo run test --force --concurrency=2(os-verify-lock): VERDICT command-exit 0;✓ 8 self-test(s) passed.check-translation-ownership.mjs --self-test: exit 0,✓ self-test: 21 case(s), each run enforced and unset ….check-locale-surface.mjs: exit 0.check-translations.mjs: exit 0,✓ translations gate passed.M, no locale paths):✓ 3 file(s) changed, no translation artifacts touched.check-translation-output.mjs --fileson the Output step's own--name-onlylist: exit 0, blocking on 0 changed translations.gen-zh-hant.mjs --check: exit 0, 71 files.check-node-floor.mjs: exit 0.Acceptance notes
content/docs/c.mdxtocontent/docs/c2.ja.mdx, exits 0. That is because--name-onlylists only the new path.content/docs/**/*.LOCALE.mdx… changed".core.quotePathon, git C-quotes a path that contains non-ASCII bytes, and a quoted path does not match thecontent/docs/prefix. Today 0 of the 472 trackedcontent/docspaths would be quoted. This behaviour is the same as before this PR.check-translation-output.mjs:95still documents its list as--name-only, which remains true for that script.Generated by Claude Code