From 260480871bf5cc3140c2d43d67f0511c1af110fe Mon Sep 17 00:00:00 2001 From: Sepehr Rasouli Date: Tue, 18 Aug 2026 08:51:24 +0330 Subject: [PATCH] Use RTD instead of re-inventing the wheel --- .github/workflows/build-and-deploy.yml | 45 ++++--- .github/workflows/build-docs-preview.yml | 90 ------------- .github/workflows/comment-docs-preview.yml | 149 --------------------- .readthedocs.yml | 24 ++++ scripts/strip_fuzzy.py | 29 ++++ 5 files changed, 82 insertions(+), 255 deletions(-) delete mode 100644 .github/workflows/build-docs-preview.yml delete mode 100644 .github/workflows/comment-docs-preview.yml create mode 100644 .readthedocs.yml create mode 100644 scripts/strip_fuzzy.py diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index 9b4203a5c..bd2b06251 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -2,14 +2,16 @@ name: Build and Deploy to GitHub Pages on: schedule: - - cron: '0 2 * * *' + - cron: '0 2 * * *' push: branches: - 3.14 workflow_dispatch: permissions: - contents: write + contents: read + pages: write + id-token: write concurrency: group: "pages" @@ -24,41 +26,52 @@ jobs: with: repository: python/cpython ref: v3.14.6 - + - name: Set up Python uses: actions/setup-python@v4 with: python-version: '3.12' - + - name: Setup virtual environment run: make venv working-directory: ./Doc - + - name: Checkout translation files uses: actions/checkout@v4 with: path: Doc/locales/fa/LC_MESSAGES - - name: Install gettext - run: sudo apt-get install -y gettext + - name: Strip stray fuzzy markers + run: python3 Doc/locales/fa/LC_MESSAGES/scripts/strip_fuzzy.py $(find Doc/locales/fa/LC_MESSAGES -name "*.po" -not -path "*/.git/*") - name: Compile .po files to .mo run: | - find Doc/locales/fa/LC_MESSAGES -name "*.po" | while read f; do + find Doc/locales/fa/LC_MESSAGES -name "*.po" -not -path "*/.git/*" | while read f; do msgfmt "$f" -o "${f%.po}.mo" done - name: Setup problem matcher uses: sphinx-doc/github-problem-matcher@v1.1 - + - name: Build documentation run: make -e SPHINXOPTS="--color -D language='fa' -D gettext_allow_fuzzy_translations=1 --keep-going" html working-directory: ./Doc - - - name: Deploy to gh-pages - uses: peaceiris/actions-gh-pages@v4 + + - name: Setup Pages + uses: actions/configure-pages@v4 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: Doc/build/html - keep_files: true - enable_jekyll: false \ No newline at end of file + path: Doc/build/html + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 \ No newline at end of file diff --git a/.github/workflows/build-docs-preview.yml b/.github/workflows/build-docs-preview.yml deleted file mode 100644 index fa8dd4147..000000000 --- a/.github/workflows/build-docs-preview.yml +++ /dev/null @@ -1,90 +0,0 @@ -# .github/workflows/build-docs-preview.yml -name: Build Docs Preview - -on: - pull_request: - types: - - opened - - synchronize - paths: - - '**/*.po' - -concurrency: - group: docs-preview-${{ github.event.pull_request.number }} - cancel-in-progress: true - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout CPython - uses: actions/checkout@v4 - with: - repository: python/cpython - ref: v3.14.6 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.12' - - - name: Setup virtual environment - run: make venv - working-directory: ./Doc - - - name: Checkout translation files (this PR's branch) - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - path: Doc/locales/fa/LC_MESSAGES - - - name: Install gettext - run: sudo apt-get install -y gettext - - - name: Compile .po files to .mo - run: | - find Doc/locales/fa/LC_MESSAGES -name "*.po" | while read f; do - msgfmt "$f" -o "${f%.po}.mo" - done - - - name: Build documentation - id: build - run: | - set +e - make -e SPHINXOPTS="--color -D language='fa' -D gettext_allow_fuzzy_translations=1 --keep-going" html 2>&1 | tee build.log - echo "exit_code=${PIPESTATUS[0]}" >> $GITHUB_OUTPUT - working-directory: ./Doc - - - name: Patch HTML static paths - # Sphinx builds _static paths as relative (e.g. ../../_static/), - # which breaks when served from a subdirectory like /previews/12/. - # We rewrite them to absolute URLs so CSS/JS load correctly - # regardless of which subdirectory the HTML file is in. - run: | - BASE="https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/previews/${{ github.event.pull_request.number }}" - find Doc/build/html -name "*.html" | while read f; do - sed -i 's|||g' "$f" - sed -i "s|href=\"\(\.\./\)*_static/|href=\"$BASE/_static/|g" "$f" - sed -i "s|src=\"\(\.\./\)*_static/|src=\"$BASE/_static/|g" "$f" - done - - - name: Move log to root - run: mv Doc/build.log build.log - - - name: Save PR number - run: echo "${{ github.event.pull_request.number }}" > pr_number.txt - - - name: Upload build result - uses: actions/upload-artifact@v4 - with: - name: build-result - path: | - build.log - pr_number.txt - - - name: Upload HTML preview - uses: actions/upload-artifact@v4 - with: - name: docs-html - path: Doc/build/html/ - retention-days: 7 \ No newline at end of file diff --git a/.github/workflows/comment-docs-preview.yml b/.github/workflows/comment-docs-preview.yml deleted file mode 100644 index b01754d5f..000000000 --- a/.github/workflows/comment-docs-preview.yml +++ /dev/null @@ -1,149 +0,0 @@ -# .github/workflows/comment-docs-preview.yml -name: Comment Docs Build Status - -on: - workflow_run: - workflows: ["Build Docs Preview"] - types: - - completed - pull_request: - types: - - closed - paths: - - '**/*.po' - -jobs: - comment: - if: github.event_name == 'workflow_run' - runs-on: ubuntu-latest - permissions: - pull-requests: write - contents: write - actions: read - - steps: - - name: Checkout repo - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Ensure gh-pages branch exists - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - if ! git ls-remote --exit-code --heads origin gh-pages; then - echo "gh-pages branch not found, creating it..." - git checkout --orphan gh-pages - git rm -rf . - echo "# Doc Previews" > README.md - git add README.md - git commit -m "chore: initialize gh-pages branch" - git push origin gh-pages - git checkout - - else - echo "gh-pages branch already exists, skipping." - fi - - - name: Download build result - uses: actions/download-artifact@v4 - with: - name: build-result - github-token: ${{ secrets.GITHUB_TOKEN }} - run-id: ${{ github.event.workflow_run.id }} - - - name: Download HTML preview - uses: actions/download-artifact@v4 - with: - name: docs-html - path: html-preview/ - github-token: ${{ secrets.GITHUB_TOKEN }} - run-id: ${{ github.event.workflow_run.id }} - - - name: Read PR number - id: pr - run: echo "number=$(find . -name "pr_number.txt" | head -1 | xargs cat)" >> $GITHUB_OUTPUT - - - name: Read build log - id: log - run: | - LOG=$(find . -name "build.log" | head -1 | xargs tail -20) - echo "content<> $GITHUB_OUTPUT - echo "$LOG" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - - name: Deploy preview to gh-pages - uses: peaceiris/actions-gh-pages@v4 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./html-preview - destination_dir: previews/${{ steps.pr.outputs.number }} - keep_files: true - enable_jekyll: false - - - name: Post comment - uses: actions/github-script@v7 - with: - script: | - const success = '${{ github.event.workflow_run.conclusion }}' === 'success'; - const icon = success ? '✅' : '❌'; - const status = success ? 'succeeded' : 'failed'; - const prNumber = ${{ steps.pr.outputs.number }}; - const owner = context.repo.owner; - const repo = context.repo.repo; - const previewUrl = `https://${owner}.github.io/${repo}/previews/${prNumber}/index.html`; - - const body = `### ${icon} Docs build ${status} - - ${success ? `📖 **[Preview the docs](${previewUrl})**` : ''} - -
- Build log (last 20 lines) - - \`\`\` - ${{ steps.log.outputs.content }} - \`\`\` - -
`; - - github.rest.issues.createComment({ - owner, - repo, - issue_number: prNumber, - body - }); - - cleanup: - if: github.event_name == 'pull_request' && github.event.action == 'closed' - runs-on: ubuntu-latest - permissions: - contents: write - - steps: - - name: Check if gh-pages exists - id: check - run: | - if git ls-remote --exit-code --heads https://github.com/${{ github.repository }}.git gh-pages; then - echo "exists=true" >> $GITHUB_OUTPUT - else - echo "exists=false" >> $GITHUB_OUTPUT - fi - - - name: Checkout gh-pages - if: steps.check.outputs.exists == 'true' - uses: actions/checkout@v4 - with: - ref: gh-pages - - - name: Remove preview folder - if: steps.check.outputs.exists == 'true' - run: | - PR=${{ github.event.pull_request.number }} - if [ -d "previews/$PR" ]; then - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git rm -rf "previews/$PR" - git commit -m "chore: remove preview for PR #$PR" - git push - else - echo "No preview folder found for PR #$PR, nothing to clean up." - fi \ No newline at end of file diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 000000000..fafcca811 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,24 @@ +version: 2 + +build: + os: ubuntu-24.04 + tools: + python: "3.12" + + commands: + - git clone --depth 1 --branch v3.14.6 https://github.com/python/cpython venv/cpython + - pip install -r venv/cpython/Doc/requirements.txt + - mkdir -p venv/cpython/Doc/locales/fa/LC_MESSAGES + - cp --parents *.po venv/cpython/Doc/locales/fa/LC_MESSAGES/ + - find */ -name "*.po" -not -path "venv/*" | xargs -I{} cp --parents {} venv/cpython/Doc/locales/fa/LC_MESSAGES/ + - find venv/cpython/Doc/locales/fa/LC_MESSAGES -name "*.po" | xargs python3 scripts/strip_fuzzy.py + - find venv/cpython/Doc/locales/fa/LC_MESSAGES -name "*.po" | while read f; do python venv/cpython/Tools/i18n/msgfmt.py -o "${f%.po}.mo" "$f"; done + - python -m sphinx -T -j auto -b html + -d $READTHEDOCS_OUTPUT/doctrees + -D language=fa + -D locale_dirs=locales + -D gettext_compact=0 + -D gettext_allow_fuzzy_translations=1 + -D html_theme_options.is_rtl=1 + venv/cpython/Doc + $READTHEDOCS_OUTPUT/html \ No newline at end of file diff --git a/scripts/strip_fuzzy.py b/scripts/strip_fuzzy.py new file mode 100644 index 000000000..1af9342b7 --- /dev/null +++ b/scripts/strip_fuzzy.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +"""Remove '#, fuzzy' marker lines from .po files. + +CPython's Tools/i18n/msgfmt.py treats a stray fuzzy flag on the file +header as applying to every entry in the file, silently producing an +empty .mo catalog. Since our translations are complete (not actually +rough drafts), we strip the marker before compiling. +""" +import sys + + +def strip_fuzzy(path: str) -> None: + with open(path, encoding="utf-8") as f: + lines = f.readlines() + + kept = [line for line in lines if not line.lstrip().startswith("#, fuzzy")] + + if kept != lines: + with open(path, "w", encoding="utf-8") as f: + f.writelines(kept) + + +def main() -> None: + for path in sys.argv[1:]: + strip_fuzzy(path) + + +if __name__ == "__main__": + main()