-
Notifications
You must be signed in to change notification settings - Fork 12
179 lines (159 loc) · 6.82 KB
/
Copy pathsync-with-cpython.yml
File metadata and controls
179 lines (159 loc) · 6.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
name: Sync with CPython
on:
schedule:
- cron: '0 4 * * *'
workflow_dispatch:
inputs:
cpython_tag:
description: 'CPython tag/branch to sync against (e.g. 3.14)'
required: false
default: '3.14'
permissions:
contents: write
issues: write
# Shared with maintenance.yml so the two never push at the same time.
concurrency:
group: repo-writes
cancel-in-progress: false
jobs:
sync:
runs-on: ubuntu-latest
timeout-minutes: 45
env:
CPYTHON_TAG: ${{ github.event.inputs.cpython_tag || '3.14' }}
steps:
- name: Checkout translation repo
uses: actions/checkout@v4
with:
fetch-depth: 0
# --- Skip the expensive build if upstream hasn't moved -------------
- name: Get upstream head
id: upstream
run: |
sha=$(git ls-remote https://github.com/python/cpython \
"refs/heads/$CPYTHON_TAG" "refs/tags/$CPYTHON_TAG" \
| head -1 | cut -f1)
echo "sha=$sha" >> "$GITHUB_OUTPUT"
# Marker lives outside the repo so `git add --all` never sees it.
echo "$sha" > "$RUNNER_TEMP/sync-marker"
- name: Check whether this upstream head was already synced
id: seen
# Fail open: no SHA -> no lookup -> full run.
if: steps.upstream.outputs.sha != ''
uses: actions/cache/restore@v4
with:
path: ${{ runner.temp }}/sync-marker
key: synced-${{ env.CPYTHON_TAG }}-${{ steps.upstream.outputs.sha }}
lookup-only: true
- name: Decide whether to run
run: |
if [ "${{ steps.seen.outputs.cache-hit }}" = "true" ] \
&& [ "${{ github.event_name }}" != "workflow_dispatch" ]; then
echo "Upstream ${{ steps.upstream.outputs.sha }} already synced; skipping."
echo "SKIP=true" >> "$GITHUB_ENV"
fi
# --- Sync ------------------------------------------------------------
- name: Set up Python
if: env.SKIP != 'true'
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install gettext
if: env.SKIP != 'true'
run: sudo apt-get install -y gettext
- name: Install Python dependencies
if: env.SKIP != 'true'
# Consider installing from CPython's Doc/requirements.txt instead of
# unpinned sphinx, so Sphinx upgrades can't change msgids on their own.
run: pip install sphinx sphinx-intl
- name: Sync msgids (fetch, build gettext, merge, validate)
if: env.SKIP != 'true'
run: python scripts/po_sync.py sync-only "$CPYTHON_TAG" --create-new
- name: Stage changes
if: env.SKIP != 'true'
run: git add --all
- name: Unstage POT-Creation-Date-only changes
if: env.SKIP != 'true'
run: python scripts/unstage_cosmetic.py
# --- Build the report from what is actually staged -------------------
- name: Build review report (new files + newly fuzzy strings)
if: env.SKIP != 'true'
run: |
report="$RUNNER_TEMP/report.md"
: > "$report"
work=$(mktemp -d)
# New PO files
new_files=$(git diff --staged --name-only --diff-filter=A -- '*.po')
if [ -n "$new_files" ]; then
{
echo "## 🆕 New PO files ($(echo "$new_files" | wc -l))"
echo "$new_files" | sed 's/^/- `/; s/$/`/'
echo ""
} >> "$report"
fi
# Fuzzy entries that are new in this run (present now, absent at HEAD)
fuzzy_out="$work/fuzzy.md"
: > "$fuzzy_out"
git diff --staged --name-only --diff-filter=M -- '*.po' |
while IFS= read -r f; do
git show "HEAD:$f" > "$work/old_full.po"
msgattrib --only-fuzzy --no-obsolete --no-wrap "$work/old_full.po" > "$work/old.po" 2>/dev/null || : > "$work/old.po"
msgattrib --only-fuzzy --no-obsolete --no-wrap "$f" > "$work/new.po" 2>/dev/null || : > "$work/new.po"
# entries in exactly one of old/new, then keep those also in new
msgcomm --less-than=2 --no-wrap "$work/old.po" "$work/new.po" > "$work/sym.po" 2>/dev/null || : > "$work/sym.po"
msgcomm --no-wrap "$work/new.po" "$work/sym.po" > "$work/added.po" 2>/dev/null || : > "$work/added.po"
count=$(grep -c '^#, .*fuzzy' "$work/added.po" || true)
if [ "${count:-0}" -gt 0 ]; then
{
echo "### \`$f\` ($count new fuzzy)"
grep -E '^msgid ".+"' "$work/added.po" | sed 's/^msgid /- /' | head -10
[ "$count" -gt 10 ] && echo "- … and $((count - 10)) more"
echo ""
} >> "$fuzzy_out"
fi
done
if [ -s "$fuzzy_out" ]; then
{ echo "## 🔍 Newly fuzzy strings"; cat "$fuzzy_out"; } >> "$report"
fi
# --- Commit + push ---------------------------------------------------
- name: Commit and push if changed
id: commit
if: env.SKIP != 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if git diff --staged --quiet; then
echo "Nothing to commit."
echo "committed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
git commit -m "chore: sync msgids with CPython $CPYTHON_TAG"
git pull --rebase
git push
echo "committed=true" >> "$GITHUB_OUTPUT"
# Only after a successful push, so a failed run can't create duplicates.
- name: Open issue for new files / newly fuzzy strings
if: env.SKIP != 'true' && steps.commit.outputs.committed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
report="$RUNNER_TEMP/report.md"
if [ -s "$report" ]; then
gh label create "translation" \
--color "0075ca" \
--description "Translation review needed" \
--repo "${{ github.repository }}" 2>/dev/null || true
echo "Triggered by sync with \`$CPYTHON_TAG\` (commit $(git rev-parse --short HEAD))." >> "$report"
gh issue create \
--title "🔍 Translation review needed after CPython sync ($(date +%Y-%m-%d))" \
--body-file "$report" \
--label "translation" \
--repo "${{ github.repository }}"
fi
# Record the upstream head as synced (only reached if everything above passed).
- name: Remember synced upstream head
if: env.SKIP != 'true' && steps.upstream.outputs.sha != ''
uses: actions/cache/save@v4
with:
path: ${{ runner.temp }}/sync-marker
key: synced-${{ env.CPYTHON_TAG }}-${{ steps.upstream.outputs.sha }}