mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-05 19:28:25 +00:00
ci(strings): gate the Compose catalog escaping check
Wires compose_escaping_check.py into the two layers that already police the identical orphan-strings desync, mirroring pre-push-orphan-strings.sh: - the fast `lint` job in build.yml, next to the orphan check - a PreToolUse hook, so a push or PR from an agent session is gated too CI is the layer that matters here. As amethyst/src/main/res/CLAUDE.md records for the orphan desync, these arrive through bot-authored PRs -- the Crowdin sync reintroduced 2,068 escaped apostrophes across 40 locales twice in two days, with no local session anywhere in the path. Verified end to end: a payload with no push exits 0 without spawning python; a push against a clean tree exits 0; a push with values-tr-rTR restored to its pre-repair state exits 1 and names the file with a per-escape breakdown. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V1CzYQvWyHfipSW7x3j4Yo
This commit is contained in:
co-authored by
Claude Opus 5
parent
f9baab0e92
commit
9585e66e60
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
# PreToolUse gate: the Compose resource catalog must not carry Android escaping.
|
||||
#
|
||||
# Fires on `git push` (Bash tool) and on the create_pull_request MCP tool.
|
||||
# Delegates to compose_escaping_check.py, which scans
|
||||
# `*/src/*/composeResources/values*/strings.xml` for \' \" \? \@ and `tools:`
|
||||
# attributes. Compose resolves only \uXXXX, \n and \t, so anything else carried
|
||||
# verbatim out of an Android res tree renders literally -- the login screen once
|
||||
# read `Don\'t have a Nostr account?`.
|
||||
#
|
||||
# Why a dedicated hook: this is reintroduced by every Crowdin sync, because
|
||||
# Crowdin holds the Android-escaped source. It came back twice in two days, 2,068
|
||||
# escaped apostrophes across 40 locales each time. Nothing in the Gradle build
|
||||
# fails on it -- the strings simply ship wrong -- so there is no slow gate this
|
||||
# stands in for; it is the only gate.
|
||||
#
|
||||
# Run the scan by hand any time with: .claude/hooks/compose_escaping_check.py
|
||||
set -uo pipefail
|
||||
|
||||
hook_dir="$(cd "$(dirname "$0")" && pwd)"
|
||||
cd "${CLAUDE_PROJECT_DIR:-.}" || exit 0
|
||||
|
||||
payload="$(cat)"
|
||||
|
||||
# Same cheap pre-filter as the orphan-strings gate: only a payload mentioning a
|
||||
# push or the PR tool can possibly match, and this runs on every Bash call.
|
||||
case "$payload" in
|
||||
*push*|*pull_request*) ;;
|
||||
*) exit 0 ;;
|
||||
esac
|
||||
|
||||
printf '%s' "$payload" | python3 "$hook_dir/lib/git_push_gate.py" || exit 0
|
||||
|
||||
exec python3 "$hook_dir/compose_escaping_check.py"
|
||||
@@ -13,6 +13,11 @@
|
||||
"type": "command",
|
||||
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/pre-push-orphan-strings.sh",
|
||||
"timeout": 30
|
||||
},
|
||||
{
|
||||
"type": "command",
|
||||
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/pre-push-compose-escaping.sh",
|
||||
"timeout": 30
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -24,6 +24,9 @@ jobs:
|
||||
- name: Orphaned translations (no locale string may outlive its default key)
|
||||
run: .claude/hooks/orphan_strings_check.py
|
||||
|
||||
- name: Compose catalog escaping (Android escapes render literally there)
|
||||
run: .claude/hooks/compose_escaping_check.py
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v6.0.0
|
||||
with:
|
||||
|
||||
Reference in New Issue
Block a user