mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-06 11:48:24 +00:00
The [ExtraTranslation] failure that took main red in 1ce583ec92 was not documented anywhere. amethyst/src/main/res/CLAUDE.md and the find-missing-translations skill both mention the lint rule, but only inside one narrow case (converting a <string> to <plurals>). Neither stated the general rule: removing or renaming a key in the default values/strings.xml orphans every locale entry that still declares it. Nor would running lint have caught it in practice. The only pre-push gate is pre-push-spotless.sh, which runs spotlessApply and nothing else, and :amethyst:lintFdroidBenchmark takes ~19 minutes on a warm daemon, so it is not a per-commit check. Add both halves: - amethyst/src/main/res/CLAUDE.md gains a "Renaming or removing a string key" section stating the same-commit rule and why Crowdin is not a cleanup step CI waits for. The trap is that Crowdin is *partly* reliable — it cleaned 32 of 47 locales — so the tree looks correct in whichever files you open. Retitled the file (it is no longer plural-only) and marked the existing sections as the plural-specific ones they always were. - orphan_strings_check.py scans every locale's resource names against its tree's default values/, across both Crowdin-managed resource systems: the Android res trees and the commons Compose-Multiplatform catalog. 0.17s against the full repo. pre-push-orphan-strings.sh wraps it as a PreToolUse gate on git push / create_pull_request, reusing the shell-tokenizing push-detection from pre-push-spotless.sh so "push" inside a commit message is not mistaken for the subcommand. - find-missing-translations gains a Common Mistakes entry pointing at both. Verified: clean on the current tree; exit 2 listing the orphans when route_video is reintroduced in two locales and a retired key is seeded in the Compose catalog; gate fires on git push and create_pull_request, stays quiet on a commit whose message contains "push" and on non-Bash tools.
62 lines
1.7 KiB
Python
Executable File
62 lines
1.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Decide whether a PreToolUse payload on stdin is a push/PR boundary.
|
|
|
|
Shared by every pre-push hook in this directory (pre-push-spotless.sh,
|
|
pre-push-orphan-strings.sh) so the gate condition is defined once. Each hook is
|
|
a separate process with its own stdin, so this is exec'd per hook rather than
|
|
run once and shared.
|
|
|
|
Exit 0 = this call publishes code (gate it). Exit 1 = let it through.
|
|
"""
|
|
|
|
import json
|
|
import shlex
|
|
import sys
|
|
|
|
# Reaching the push subcommand means stepping over git's global options first.
|
|
GLOBAL_WITH_ARG = {"-c", "-C", "--namespace", "--git-dir", "--work-tree", "--exec-path"}
|
|
|
|
|
|
def is_boundary(data):
|
|
tool = data.get("tool_name", "")
|
|
if tool.endswith("create_pull_request"):
|
|
return True
|
|
if tool != "Bash":
|
|
return False
|
|
|
|
cmd = (data.get("tool_input") or {}).get("command", "")
|
|
# Tokenize like a shell so `push` inside a quoted commit message or heredoc
|
|
# stays one token and is NOT mistaken for the push subcommand.
|
|
try:
|
|
tokens = shlex.split(cmd, comments=True)
|
|
except ValueError:
|
|
tokens = cmd.split()
|
|
|
|
for i, token in enumerate(tokens):
|
|
if token != "git" and not token.endswith("/git"):
|
|
continue
|
|
j = i + 1
|
|
while j < len(tokens):
|
|
tok = tokens[j]
|
|
if tok in GLOBAL_WITH_ARG:
|
|
j += 2
|
|
elif tok.startswith("-"):
|
|
j += 1
|
|
else:
|
|
break
|
|
if j < len(tokens) and tokens[j] == "push":
|
|
return True
|
|
return False
|
|
|
|
|
|
def main():
|
|
try:
|
|
data = json.load(sys.stdin)
|
|
except Exception:
|
|
return 1
|
|
return 0 if is_boundary(data) else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|