debugging workflow #18
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: Check Translation Coverage | |
| on: | |
| pull_request: | |
| paths: | |
| - 'docs/en/**' | |
| - 'docs/zh/**' | |
| - 'docs/ja/**' | |
| issue_comment: | |
| types: [created] | |
| permissions: | |
| pull-requests: write | |
| contents: read | |
| jobs: | |
| check-translation: | |
| name: Check if all languages are updated | |
| # This job only runs on pull_request events, not on issue_comment | |
| # This ensures we never checkout untrusted code from comments | |
| if: github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - name: Get changed files | |
| id: changed-files | |
| run: | | |
| # Get the list of changed files in the PR | |
| CHANGED_FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}) | |
| echo "Changed files:" | |
| echo "$CHANGED_FILES" | |
| # Extract unique basenames from docs files and check which languages have them | |
| declare -A file_langs | |
| while IFS= read -r file; do | |
| if [[ "$file" == docs/en/* ]]; then | |
| basename="${file#docs/en/}" | |
| file_langs["$basename"]+="en," | |
| elif [[ "$file" == docs/zh/* ]]; then | |
| basename="${file#docs/zh/}" | |
| file_langs["$basename"]+="zh," | |
| elif [[ "$file" == docs/ja/* ]]; then | |
| basename="${file#docs/ja/}" | |
| file_langs["$basename"]+="ja," | |
| fi | |
| done <<< "$CHANGED_FILES" | |
| # Check if any doc file is missing from languages | |
| INCOMPLETE_FILES="" | |
| for basename in "${!file_langs[@]}"; do | |
| langs="${file_langs[$basename]}" | |
| has_en=false | |
| has_zh=false | |
| has_ja=false | |
| if [[ "$langs" == *"en,"* ]]; then has_en=true; fi | |
| if [[ "$langs" == *"zh,"* ]]; then has_zh=true; fi | |
| if [[ "$langs" == *"ja,"* ]]; then has_ja=true; fi | |
| # If the file exists in only 1 or 2 languages, mark as incomplete | |
| count=0 | |
| if [ "$has_en" = true ]; then count=$((count + 1)); fi | |
| if [ "$has_zh" = true ]; then count=$((count + 1)); fi | |
| if [ "$has_ja" = true ]; then count=$((count + 1)); fi | |
| if [ $count -gt 0 ] && [ $count -lt 3 ]; then | |
| missing_langs="" | |
| if [ "$has_en" = false ]; then missing_langs+="en,"; fi | |
| if [ "$has_zh" = false ]; then missing_langs+="zh,"; fi | |
| if [ "$has_ja" = false ]; then missing_langs+="ja,"; fi | |
| INCOMPLETE_FILES+="$basename:$missing_langs;" | |
| fi | |
| done | |
| if [ -n "$INCOMPLETE_FILES" ]; then | |
| echo "incomplete_files=$INCOMPLETE_FILES" >> $GITHUB_OUTPUT | |
| echo "has_incomplete=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "has_incomplete=false" >> $GITHUB_OUTPUT | |
| fi | |
| echo "Incomplete files: $INCOMPLETE_FILES" | |
| # Ensure the script exits successfully | |
| exit 0 | |
| - name: Comment on PR if translation needed | |
| if: steps.changed-files.outputs.has_incomplete == 'true' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const incompleteFiles = '${{ steps.changed-files.outputs.incomplete_files }}'; | |
| // Parse the incomplete files string | |
| const files = incompleteFiles.split(';').filter(f => f.trim()); | |
| let fileDetails = ''; | |
| for (const fileEntry of files) { | |
| if (!fileEntry) continue; | |
| const [filename, missingLangs] = fileEntry.split(':'); | |
| const langs = missingLangs.split(',').filter(l => l.trim()); | |
| const langNames = langs.map(l => { | |
| if (l === 'en') return 'English'; | |
| if (l === 'zh') return 'Chinese'; | |
| if (l === 'ja') return 'Japanese'; | |
| return l; | |
| }); | |
| fileDetails += `\n- **${filename}** - Missing in: ${langNames.join(', ')}`; | |
| } | |
| const commentBody = `## π Translation Check | |
| This PR contains documentation files that are not translated to all languages: | |
| ${fileDetails} | |
| --- | |
| **Should a translation job be run to create the missing translations?** | |
| - To **request** a translation job, comment: \`/translate-request\` | |
| - To **approve** a translation job (docs-maintainer team only), comment: \`/translate-approve\` | |
| > **Note:** Only members of the \`StarRocks/docs-maintainer\` team can approve translation jobs.`; | |
| // Check if we already commented on this PR | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| }); | |
| const botComment = comments.find(comment => | |
| comment.user.type === 'Bot' && | |
| comment.body.includes('π Translation Check') | |
| ); | |
| if (botComment) { | |
| // Update existing comment | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: botComment.id, | |
| body: commentBody | |
| }); | |
| } else { | |
| // Create new comment | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: commentBody | |
| }); | |
| } | |
| handle-translation-commands: | |
| name: Handle translation commands | |
| if: | | |
| github.event_name == 'issue_comment' && | |
| github.event.issue.pull_request && | |
| (contains(github.event.comment.body, '/translate-request') || contains(github.event.comment.body, '/translate-approve')) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check if comment is a translation request | |
| if: contains(github.event.comment.body, '/translate-request') | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const commentBody = `β Translation job requested by @${{ github.event.comment.user.login }}. | |
| Waiting for approval from a member of the \`StarRocks/docs-maintainer\` team. | |
| To approve, comment: \`/translate-approve\``; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: commentBody | |
| }); | |
| - name: Check team membership and approve | |
| if: contains(github.event.comment.body, '/translate-approve') | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.MEMBERSHIP_TOKEN || secrets.GITHUB_TOKEN }} | |
| script: | | |
| const commenter = '${{ github.event.comment.user.login }}'; | |
| try { | |
| // Check if the commenter is a member of the docs-maintainer team | |
| let membership = null; | |
| try { | |
| const response = await github.rest.teams.getMembershipForUserInOrg({ | |
| org: 'StarRocks', | |
| team_slug: 'docs-maintainer', | |
| username: commenter | |
| }); | |
| membership = response.data; | |
| } catch (error) { | |
| if (error.status !== 404) { | |
| throw error; | |
| } | |
| // 404 means user is not a member, membership stays null | |
| } | |
| if (membership && (membership.state === 'active')) { | |
| // User is a team member, approve the translation | |
| const commentBody = `β Translation job **approved** by @${commenter} (docs-maintainer team member). | |
| π The translation job will be triggered. | |
| _Note: Translation job execution is configured separately._`; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: commentBody | |
| }); | |
| // Add label to indicate translation is approved | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| labels: ['translation-approved'] | |
| }); | |
| } else { | |
| // User is not a team member | |
| const commentBody = `β @${commenter}, you do not have permission to approve translation jobs. | |
| Only members of the \`StarRocks/docs-maintainer\` team can approve translations.`; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: commentBody | |
| }); | |
| } | |
| } catch (error) { | |
| console.error('Error checking team membership:', error); | |
| const commentBody = `β οΈ Error checking team membership for @${commenter}. | |
| Error: ${error.message} | |
| Please ensure: | |
| 1. The \`StarRocks/docs-maintainer\` team exists | |
| 2. The GitHub token has the necessary permissions to check team membership | |
| 3. You are a member of the \`StarRocks\` organization`; | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: commentBody | |
| }); | |
| } |