|
name: Sync with CPython |
|
|
|
on: |
|
schedule: |
|
- cron: '0 4 * * *' |
|
workflow_dispatch: |
|
inputs: |
|
cpython_tag: |
|
description: 'CPython tag/branch to sync against (e.g. 3.15)' |
|
required: false |
|
default: '3.15' |
|
|
|
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.15' }} |
|
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' |
|
# polib is used by scripts/review_report.py to build the issue body. |
|
# Consider installing sphinx from CPython's Doc/requirements.txt |
|
# instead of unpinned, so Sphinx upgrades can't change msgids on |
|
# their own. |
|
run: pip install sphinx sphinx-intl polib |
|
|
|
- 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 ------------------- |
|
# New PO files, newly fuzzy strings (old -> new diff) and new |
|
# untranslated strings. Writes an empty file if there is nothing to |
|
# report, in which case no issue is opened. |
|
- name: Build review report (new files, newly fuzzy, new untranslated) |
|
if: env.SKIP != 'true' |
|
run: python scripts/review_report.py --output "$RUNNER_TEMP/report.md" |
|
|
|
# --- 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 / fuzzy / untranslated 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 |
|
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 "تغییرات خودکار در ترجمهها" \ |
|
--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 }} |