Skip to content

.github/workflows/sync_docs_update.yml #4

.github/workflows/sync_docs_update.yml

.github/workflows/sync_docs_update.yml #4

name: Update Translation PR
on:
pull_request:
types: [synchronize]
paths:
- 'docs.json'
- 'en/**/*.md'
- 'en/**/*.mdx'
permissions:
contents: write
pull-requests: write
actions: read
jobs:
update-translation:
runs-on: ubuntu-latest
# Only run if this is an English-only PR update
if: github.event.pull_request.draft == false
steps:
- name: Checkout PR
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Check if PR is English-only
id: check-pr-type
run: |
echo "Checking if this PR contains only English changes..."
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
# Use PR analyzer to check PR type
cd tools/translate
python pr_analyzer.py "$BASE_SHA" "$HEAD_SHA" > /tmp/pr_analysis_output.txt 2>&1
if [ $? -eq 0 ]; then
# Parse analyzer output
source /tmp/pr_analysis_output.txt
echo "PR Type: $pr_type"
echo "pr_type=$pr_type" >> $GITHUB_OUTPUT
if [ "$pr_type" = "english" ]; then
echo "✅ English-only PR detected - proceeding with translation update"
echo "should_update=true" >> $GITHUB_OUTPUT
else
echo "ℹ️ Not an English-only PR (type: $pr_type) - skipping translation update"
echo "should_update=false" >> $GITHUB_OUTPUT
fi
else
echo "❌ PR analysis failed - likely mixed content, skipping translation update"
echo "should_update=false" >> $GITHUB_OUTPUT
echo "pr_type=unknown" >> $GITHUB_OUTPUT
fi
- name: Find associated translation PR
if: steps.check-pr-type.outputs.should_update == 'true'
id: find-translation-pr
run: |
PR_NUMBER=${{ github.event.pull_request.number }}
echo "Looking for translation PR associated with PR #${PR_NUMBER}..."
# Search for translation PR by branch name pattern
TRANSLATION_PR_DATA=$(gh pr list \
--search "head:docs-sync-pr-${PR_NUMBER}" \
--json number,title,url,state \
--jq '.[0] // empty' 2>/dev/null || echo "")
if [ -n "$TRANSLATION_PR_DATA" ] && [ "$TRANSLATION_PR_DATA" != "null" ]; then
TRANSLATION_PR_NUMBER=$(echo "$TRANSLATION_PR_DATA" | jq -r '.number')
TRANSLATION_PR_STATE=$(echo "$TRANSLATION_PR_DATA" | jq -r '.state')
TRANSLATION_PR_URL=$(echo "$TRANSLATION_PR_DATA" | jq -r '.url')
if [ "$TRANSLATION_PR_STATE" = "OPEN" ]; then
echo "✅ Found active translation PR #${TRANSLATION_PR_NUMBER}"
echo "translation_pr_number=$TRANSLATION_PR_NUMBER" >> $GITHUB_OUTPUT
echo "translation_pr_url=$TRANSLATION_PR_URL" >> $GITHUB_OUTPUT
echo "found_translation_pr=true" >> $GITHUB_OUTPUT
else
echo "ℹ️ Found translation PR #${TRANSLATION_PR_NUMBER} but it's ${TRANSLATION_PR_STATE} - skipping update"
echo "found_translation_pr=false" >> $GITHUB_OUTPUT
fi
else
echo "ℹ️ No translation PR found for PR #${PR_NUMBER} - this might be the first update"
echo "found_translation_pr=false" >> $GITHUB_OUTPUT
fi
- name: Install dependencies
if: steps.find-translation-pr.outputs.found_translation_pr == 'true'
run: |
cd tools/translate
pip install httpx aiofiles python-dotenv
- name: Update translations
if: steps.find-translation-pr.outputs.found_translation_pr == 'true'
id: update-translations
env:
DIFY_API_KEY: ${{ secrets.DIFY_API_KEY }}
run: |
echo "Updating translations for PR #${{ github.event.pull_request.number }}..."
PR_NUMBER=${{ github.event.pull_request.number }}
SYNC_BRANCH="docs-sync-pr-${PR_NUMBER}"
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
# Switch to translation branch
git fetch origin "$SYNC_BRANCH:$SYNC_BRANCH" || {
echo "❌ Could not fetch translation branch $SYNC_BRANCH"
echo "update_successful=false" >> $GITHUB_OUTPUT
exit 0
}
git checkout "$SYNC_BRANCH"
# Reset translation branch to latest main to get fresh translations
git reset --hard origin/main
# Re-run translation analysis and generation
cd tools/translate
# Create updated sync script
cat > update_translations.py <<'EOF'
import json
import sys
import os
import asyncio
from pathlib import Path
# Add parent directory to path
sys.path.append(os.path.dirname(__file__))
from sync_and_translate import DocsSynchronizer
from pr_analyzer import PRAnalyzer
async def update_translations():
base_sha = sys.argv[1]
head_sha = sys.argv[2]
# Analyze changes
analyzer = PRAnalyzer(base_sha, head_sha)
result = analyzer.categorize_pr()
if result['type'] != 'english':
print(f"PR type is {result['type']}, not english - skipping")
return False
# Initialize synchronizer
api_key = os.environ.get("DIFY_API_KEY")
if not api_key:
print("Error: DIFY_API_KEY not set")
return False
synchronizer = DocsSynchronizer(api_key)
# Get English files that need translation
file_categories = result['files']
english_files = file_categories['english']
results = {
"translated": [],
"failed": [],
"skipped": [],
"updated": True
}
# Translate English files
for file_path in english_files[:10]: # Limit to 10 files for safety
print(f"Updating translations for: {file_path}")
try:
for target_lang in ["zh-hans", "ja-jp"]:
target_path = file_path.replace("en/", f"{target_lang}/")
success = await synchronizer.translate_file_with_notice(
file_path,
target_path,
target_lang
)
if success:
results["translated"].append(target_path)
else:
results["failed"].append(target_path)
except Exception as e:
print(f"Error processing {file_path}: {e}")
results["failed"].append(file_path)
# Handle docs.json structure sync if needed
docs_changes = result['docs_json_changes']
if docs_changes['any_docs_json_changes']:
print("Updating docs.json structure...")
try:
sync_log = synchronizer.sync_docs_json_structure()
print("\n".join(sync_log))
except Exception as e:
print(f"Error syncing docs.json structure: {e}")
# Save results
with open("/tmp/update_results.json", "w") as f:
json.dump(results, f, indent=2)
return len(results["failed"]) == 0
if __name__ == "__main__":
success = asyncio.run(update_translations())
sys.exit(0 if success else 1)
EOF
# Run the update
python update_translations.py "$BASE_SHA" "$HEAD_SHA"
UPDATE_EXIT_CODE=$?
echo "update_exit_code=$UPDATE_EXIT_CODE" >> $GITHUB_OUTPUT
# Check for changes
if [[ -n $(git status --porcelain) ]]; then
echo "has_changes=true" >> $GITHUB_OUTPUT
echo "✅ Translation updates detected"
else
echo "has_changes=false" >> $GITHUB_OUTPUT
echo "ℹ️ No translation updates needed"
fi
- name: Commit and push translation updates
if: steps.update-translations.outputs.has_changes == 'true'
id: commit-updates
run: |
PR_NUMBER=${{ github.event.pull_request.number }}
SYNC_BRANCH="docs-sync-pr-${PR_NUMBER}"
git config user.name 'github-actions[bot]'
git config user.email 'github-actions[bot]@users.noreply.github.com'
git add .
git commit -m "🔄 Update translations for PR #${PR_NUMBER}
Updated translations following changes in PR #${PR_NUMBER}.
Auto-updated by translation workflow.
🤖 Generated with GitHub Actions"
# Push updates to translation branch
git push origin "$SYNC_BRANCH" --force
echo "commit_successful=true" >> $GITHUB_OUTPUT
echo "✅ Translation updates committed and pushed"
- name: Comment on original PR about update
if: steps.update-translations.outputs.has_changes == 'true' && steps.commit-updates.outputs.commit_successful == 'true'
uses: actions/github-script@v7
continue-on-error: true
with:
script: |
const fs = require('fs');
const prNumber = ${{ github.event.pull_request.number }};
const translationPrNumber = '${{ steps.find-translation-pr.outputs.translation_pr_number }}';
const translationPrUrl = '${{ steps.find-translation-pr.outputs.translation_pr_url }}';
// Load update results
let results = { translated: [], failed: [], skipped: [] };
try {
results = JSON.parse(fs.readFileSync('/tmp/update_results.json', 'utf8'));
} catch (e) {
console.log('Could not load update results');
}
let comment = `## 🔄 Translation PR Updated
Your English documentation changes have been automatically translated and the translation PR has been updated.
### 🔗 Updated Translation PR: [#${translationPrNumber}](${translationPrUrl})
`;

Check failure on line 279 in .github/workflows/sync_docs_update.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/sync_docs_update.yml

Invalid workflow file

You have an error in your yaml syntax on line 279
if (results.translated && results.translated.length > 0) {
comment += `### ✅ Updated Translations (${results.translated.length} files):\n`;
results.translated.slice(0, 6).forEach(file => {
comment += `- \`${file}\`\n`;
});
if (results.translated.length > 6) {
comment += `- ... and ${results.translated.length - 6} more files\n`;
}
comment += '\n';
}
if (results.failed && results.failed.length > 0) {
comment += `### ⚠️ Update Issues (${results.failed.length}):\n`;
results.failed.slice(0, 3).forEach(file => {
comment += `- \`${file}\`\n`;
});
comment += '\n';
}
comment += `### 🔄 What's Updated:
- **Translation Files**: All corresponding zh-hans and ja-jp files
- **Navigation Structure**: Updated docs.json if needed
- **Automatic**: This update happened automatically when you updated your PR
---
🤖 _Automatic update from the translation workflow._`;
try {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: comment
});
} catch (error) {
console.log('Could not comment on original PR:', error.message);
}
- name: Comment on translation PR about update
if: steps.update-translations.outputs.has_changes == 'true' && steps.commit-updates.outputs.commit_successful == 'true'
uses: actions/github-script@v7
continue-on-error: true
with:
script: |
const fs = require('fs');
const prNumber = ${{ github.event.pull_request.number }};
const translationPrNumber = '${{ steps.find-translation-pr.outputs.translation_pr_number }}';
// Load update results
let results = { translated: [], failed: [], skipped: [] };
try {
results = JSON.parse(fs.readFileSync('/tmp/update_results.json', 'utf8'));
} catch (e) {
console.log('Could not load update results');
}
const updateComment = `## 🔄 Automatic Translation Update
This translation PR has been automatically updated following changes in the original PR #${prNumber}.
### 📝 What Was Updated:
- **Source**: Changes from PR #${prNumber}
- **Updated Files**: ${results.translated ? results.translated.length : 0} translation files
- **Languages**: Chinese (zh-hans) and Japanese (ja-jp)
### ✅ Translation Status:
${results.translated && results.translated.length > 0 ?
`**Successfully Updated (${results.translated.length} files):**\n` +
results.translated.slice(0, 5).map(f => `- \`${f}\``).join('\n') +
(results.translated.length > 5 ? `\n- ... and ${results.translated.length - 5} more` : '') :
'- All translations are up to date'}
${results.failed && results.failed.length > 0 ?
`\n### ⚠️ Update Issues:\n${results.failed.slice(0, 3).map(f => `- \`${f}\``).join('\n')}` : ''}
### 🔄 Review Process:
1. **Automatic Update**: This PR was updated automatically
2. **Review Needed**: Please review the updated translations
3. **Independent Merge**: This PR can still be merged independently
---
🤖 _This update was triggered automatically by changes to PR #${prNumber}._`;
try {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: translationPrNumber,
body: updateComment
});
} catch (error) {
console.log('Could not comment on translation PR:', error.message);
}
- name: Handle no updates needed
if: steps.find-translation-pr.outputs.found_translation_pr == 'true' && steps.update-translations.outputs.has_changes != 'true'
uses: actions/github-script@v7
continue-on-error: true
with:
script: |
const prNumber = ${{ github.event.pull_request.number }};
const translationPrNumber = '${{ steps.find-translation-pr.outputs.translation_pr_number }}';
const comment = `## ✅ Translation PR Already Up to Date
Your changes to PR #${prNumber} did not require translation updates.
The translation PR [#${translationPrNumber}](https://github.com/${{ github.repository }}/pull/${translationPrNumber}) remains current.
🤖 _Automatic check from the translation workflow._`;
try {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: comment
});
} catch (error) {
console.log('Could not comment on original PR:', error.message);
}