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 \