diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index 6f5b9cfd7..9b4203a5c 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -2,16 +2,14 @@ name: Build and Deploy to GitHub Pages on: schedule: - - cron: '0 2 * * *' + - cron: '0 2 * * *' push: branches: - 3.14 workflow_dispatch: permissions: - contents: read - pages: write - id-token: write + contents: write concurrency: group: "pages" @@ -26,16 +24,16 @@ 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: @@ -52,26 +50,15 @@ jobs: - 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: Setup Pages - uses: actions/configure-pages@v4 - - - name: Upload artifact - uses: actions/upload-pages-artifact@v3 - with: - 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 + - name: Deploy to gh-pages + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: Doc/build/html + keep_files: true + enable_jekyll: false \ No newline at end of file diff --git a/.github/workflows/build-docs-preview.yml b/.github/workflows/build-docs-preview.yml new file mode 100644 index 000000000..fa8dd4147 --- /dev/null +++ b/.github/workflows/build-docs-preview.yml @@ -0,0 +1,90 @@ +# .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 new file mode 100644 index 000000000..b01754d5f --- /dev/null +++ b/.github/workflows/comment-docs-preview.yml @@ -0,0 +1,149 @@ +# .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/.github/workflows/sync-with-cpython.yml b/.github/workflows/sync-with-cpython.yml index db5e19e08..2433581e0 100644 --- a/.github/workflows/sync-with-cpython.yml +++ b/.github/workflows/sync-with-cpython.yml @@ -70,7 +70,7 @@ jobs: rel="${f#.pot-templates/}" po="${rel%.pot}.po" if [ -f "$po" ]; then - msgmerge --update --backup=off --no-location "$po" "$f" + msgmerge --update --backup=off --no-location --no-wrap "$po" "$f" fi done @@ -149,16 +149,31 @@ jobs: - name: Clean up scratch files run: rm -rf .cpython-src .pot-templates + - name: Stage changes + run: git add --all + + - name: Unstage POT-Creation-Date-only changes + run: | + git diff --staged --name-only | while read f; do + if git diff --staged -U0 -- "$f" \ + | grep '^[+-]' \ + | grep -v '^[+-][+-][+-]' \ + | grep -qv 'POT-Creation-Date'; then + : # has real changes, keep staged + else + git restore --staged "$f" + git restore "$f" + fi + done + - name: Commit if changed run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - git add --all - git diff --staged -U0 \ - | grep '^[+-]' \ - | grep -v '^[+-][+-][+-]' \ - | grep -qv 'POT-Creation-Date' \ - || { echo "Only POT-Creation-Date changed, skipping commit."; exit 0; } + if git diff --staged --quiet; then + echo "Nothing to commit, skipping." + exit 0 + fi git commit -m \ "chore: sync msgids with CPython ${{ github.event.inputs.cpython_tag || 'v3.14.6' }}" git push \ No newline at end of file diff --git a/Makefile b/Makefile index 6a1c5a63d..93a3acfab 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,7 @@ CPYTHON_CURRENT_COMMIT := d26c2fe7a2833606b3fb8d9789149d8696978d86 LANGUAGE := fa -BRANCH := 3.13 +BRANCH := 3.14 EXCLUDED := \ whatsnew/2.?.po \