Sync with CPython #54
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
| 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' | |
| # 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 | |
| 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 }} |