diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 2d2e921a..4ca3deb3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -25,11 +25,9 @@ ## 📝 Description | 描述 -**English:** +**English:** | **中文:** -**中文:** - --- @@ -57,11 +55,7 @@ ## 📋 Changes Made | 具体变更 -**English:** -- -- - -**中文:** +**English:** | **中文:** - - @@ -94,10 +88,7 @@ ## 📚 Additional Notes | 补充说明 -**English:** - - -**中文:** +**English:** | **中文:** --- diff --git a/.github/PULL_REQUEST_TEMPLATE/backend.md b/.github/PULL_REQUEST_TEMPLATE/backend.md index 16ac8def..dfc354c3 100644 --- a/.github/PULL_REQUEST_TEMPLATE/backend.md +++ b/.github/PULL_REQUEST_TEMPLATE/backend.md @@ -7,11 +7,9 @@ ## 📝 Description | 描述 -**English:** +**English:** | **中文:** -**中文:** - --- @@ -36,11 +34,7 @@ ## 📋 Changes Made | 具体变更 -**English:** -- -- - -**中文:** +**English:** | **中文:** - - @@ -111,10 +105,7 @@ Test output here | 测试输出 ## 📚 Additional Notes | 补充说明 -**English:** - - -**中文:** +**English:** | **中文:** --- diff --git a/.github/PULL_REQUEST_TEMPLATE/docs.md b/.github/PULL_REQUEST_TEMPLATE/docs.md index 66e3f344..2ce9a90c 100644 --- a/.github/PULL_REQUEST_TEMPLATE/docs.md +++ b/.github/PULL_REQUEST_TEMPLATE/docs.md @@ -7,10 +7,7 @@ ## 📝 Description | 描述 -**English:** - - -**中文:** +**English:** | **中文:** --- @@ -36,11 +33,7 @@ ## 📋 Changes Made | 具体变更 -**English:** -- -- - -**中文:** +**English:** | **中文:** - - @@ -88,10 +81,7 @@ ## 📚 Additional Notes | 补充说明 -**English:** - - -**中文:** +**English:** | **中文:** --- diff --git a/.github/PULL_REQUEST_TEMPLATE/frontend.md b/.github/PULL_REQUEST_TEMPLATE/frontend.md index 849d3e12..b95a20d0 100644 --- a/.github/PULL_REQUEST_TEMPLATE/frontend.md +++ b/.github/PULL_REQUEST_TEMPLATE/frontend.md @@ -7,10 +7,7 @@ ## 📝 Description | 描述 -**English:** - - -**中文:** +**English:** | **中文:** --- @@ -35,11 +32,7 @@ ## 📋 Changes Made | 具体变更 -**English:** -- -- - -**中文:** +**English:** | **中文:** - - @@ -110,10 +103,7 @@ ## 📚 Additional Notes | 补充说明 -**English:** - - -**中文:** +**English:** | **中文:** --- diff --git a/.github/PULL_REQUEST_TEMPLATE/general.md b/.github/PULL_REQUEST_TEMPLATE/general.md index 229aedcb..23773e4c 100644 --- a/.github/PULL_REQUEST_TEMPLATE/general.md +++ b/.github/PULL_REQUEST_TEMPLATE/general.md @@ -7,10 +7,7 @@ ## 📝 Description | 描述 -**English:** - - -**中文:** +**English:** | **中文:** --- @@ -39,11 +36,7 @@ ## 📋 Changes Made | 具体变更 -**English:** -- -- - -**中文:** +**English:** | **中文:** - - @@ -89,10 +82,7 @@ ## 📚 Additional Notes | 补充说明 -**English:** - - -**中文:** +**English:** | **中文:** --- diff --git a/.github/workflows/pr-template-suggester.yml b/.github/workflows/pr-template-suggester.yml index 7f216ca1..9e74a9e4 100644 --- a/.github/workflows/pr-template-suggester.yml +++ b/.github/workflows/pr-template-suggester.yml @@ -15,7 +15,7 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Analyze PR files and suggest template + - name: Analyze PR files and auto-apply template uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} @@ -26,49 +26,28 @@ jobs: pull_number: context.issue.number, }); - let goFiles = 0; - let jsFiles = 0; - let tsFiles = 0; - let mdFiles = 0; - let otherFiles = 0; + let goFiles = 0, jsFiles = 0, tsFiles = 0, mdFiles = 0, otherFiles = 0; for (const file of files) { const filename = file.filename.toLowerCase(); - if (filename.endsWith('.go')) { - goFiles++; - } else if (filename.endsWith('.js') || filename.endsWith('.jsx')) { - jsFiles++; - } else if (filename.endsWith('.ts') || filename.endsWith('.tsx') || filename.endsWith('.vue')) { - tsFiles++; - } else if (filename.endsWith('.md')) { - mdFiles++; - } else { - otherFiles++; - } + if (filename.endsWith('.go')) goFiles++; + else if (filename.endsWith('.js') || filename.endsWith('.jsx')) jsFiles++; + else if (filename.endsWith('.ts') || filename.endsWith('.tsx') || filename.endsWith('.vue')) tsFiles++; + else if (filename.endsWith('.md')) mdFiles++; + else otherFiles++; } const totalFiles = goFiles + jsFiles + tsFiles + mdFiles + otherFiles; - if (totalFiles === 0) { - console.log('No files changed'); - return; - } + if (totalFiles === 0) { console.log('No files changed'); return; } - let suggestedTemplate = null; - let templateEmoji = ''; - let templateLabel = ''; + let suggestedTemplate = null, templateEmoji = '', templateLabel = ''; if (goFiles / totalFiles > 0.5) { - suggestedTemplate = 'backend'; - templateEmoji = '🔧'; - templateLabel = 'backend'; + suggestedTemplate = 'backend'; templateEmoji = '🔧'; templateLabel = 'backend'; } else if ((jsFiles + tsFiles) / totalFiles > 0.5) { - suggestedTemplate = 'frontend'; - templateEmoji = '🎨'; - templateLabel = 'frontend'; + suggestedTemplate = 'frontend'; templateEmoji = '🎨'; templateLabel = 'frontend'; } else if (mdFiles / totalFiles > 0.7) { - suggestedTemplate = 'docs'; - templateEmoji = '📝'; - templateLabel = 'documentation'; + suggestedTemplate = 'docs'; templateEmoji = '📝'; templateLabel = 'documentation'; } const { data: pr } = await github.rest.pulls.get({ @@ -92,58 +71,119 @@ jobs: issue_number: context.issue.number, labels: [templateLabel] }); - console.log(`Added label: ${templateLabel}`); + console.log('Added label: ' + templateLabel); } catch (error) { - console.log(`Label might not exist, skipping...`); + console.log('Label might not exist, skipping...'); } } + function isPRBodyEmpty(body) { + if (!body || body.trim().length < 100) return true; + const hasEmptyDescription = body.includes('**English:**') && body.match(/\*\*English:\*\*\s*\n\s*\n\s*\n/); + const hasEmptyChanges = body.includes('具体变更') && body.match(/\*\*中文:\*\*\s*\n\s*-\s*\n\s*-\s*\n/); + if (hasEmptyDescription || hasEmptyChanges) return true; + const descMatch = body.match(/\*\*English:\*\*[||]\s*\*\*中文:\*\*\s*\n\s*(.+)/); + if (!descMatch || descMatch[1].trim().length < 10) return true; + return false; + } + if (suggestedTemplate && usingDefaultTemplate) { - const templateUrl = `https://raw.githubusercontent.com/${context.repo.owner}/${context.repo.repo}/dev/.github/PULL_REQUEST_TEMPLATE/${suggestedTemplate}.md`; + const shouldAutoApply = isPRBodyEmpty(prBody); + const templatePath = '.github/PULL_REQUEST_TEMPLATE/' + suggestedTemplate + '.md'; - let fileStats = []; - if (goFiles > 0) fileStats.push(`🔧 Go files: ${goFiles}`); - if (jsFiles > 0) fileStats.push(`🎨 JavaScript files: ${jsFiles}`); - if (tsFiles > 0) fileStats.push(`🎨 TypeScript files: ${tsFiles}`); - if (mdFiles > 0) fileStats.push(`📝 Markdown files: ${mdFiles}`); - if (otherFiles > 0) fileStats.push(`📦 Other files: ${otherFiles}`); + if (shouldAutoApply) { + try { + const { data: templateFile } = await github.rest.repos.getContent({ + owner: context.repo.owner, + repo: context.repo.repo, + path: templatePath, + ref: context.payload.pull_request.head.ref + }); - const fileStatsText = fileStats.map(s => `- ${s}`).join('\n'); + const templateContent = Buffer.from(templateFile.content, 'base64').toString('utf-8'); - const comment = `## ${templateEmoji} 建议使用专用模板 | Suggested Template + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number, + body: templateContent + }); - 您的PR主要包含 **${suggestedTemplate}** 相关的变更。我们建议使用更适合的模板以简化填写。 + console.log('Auto-applied ' + suggestedTemplate + ' template'); - Your PR primarily contains **${suggestedTemplate}** changes. We suggest using a more suitable template to simplify filling. + let fileStats = []; + if (goFiles > 0) fileStats.push('- 🔧 Go files: ' + goFiles); + if (jsFiles > 0) fileStats.push('- 🎨 JavaScript files: ' + jsFiles); + if (tsFiles > 0) fileStats.push('- 🎨 TypeScript files: ' + tsFiles); + if (mdFiles > 0) fileStats.push('- 📝 Markdown files: ' + mdFiles); + if (otherFiles > 0) fileStats.push('- 📦 Other files: ' + otherFiles); + const fileStatsText = fileStats.join('\n'); - **文件统计 | File Statistics** - ${fileStatsText} + const notifyComment = '## ' + templateEmoji + ' 已自动应用专用模板 | Auto-Applied Template\n\n' + + '检测到您的PR主要包含 **' + suggestedTemplate + '** 相关的变更,系统已自动为您应用相应的模板。\n\n' + + 'Detected that your PR primarily contains **' + suggestedTemplate + '** changes. The appropriate template has been automatically applied.\n\n' + + '**文件统计 | File Statistics**\n' + fileStatsText + '\n\n' + + '**已应用模板 | Applied Template**\n`' + templatePath + '`\n\n' + + '✨ 您现在可以直接在PR描述中填写相关信息了!\n\n' + + '✨ You can now fill in the relevant information in the PR description!'; - **推荐模板 | Recommended Template** - \`\`\` - .github/PULL_REQUEST_TEMPLATE/${suggestedTemplate}.md - \`\`\` + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: notifyComment + }); - **如何使用 | How to use** - 1. 编辑PR描述 | Edit PR description - 2. 复制 [${suggestedTemplate} 模板内容](${templateUrl}) | Copy [${suggestedTemplate} template content](${templateUrl}) - 3. 或在创建PR时使用URL参数 | Or use URL parameter when creating PR - \`?template=${suggestedTemplate}.md\` + } catch (error) { + console.log('Failed to fetch or apply template: ' + error.message); + const templateUrl = 'https://raw.githubusercontent.com/' + context.repo.owner + '/' + context.repo.repo + '/dev/.github/PULL_REQUEST_TEMPLATE/' + suggestedTemplate + '.md'; + const fallbackComment = '## ' + templateEmoji + ' 建议使用专用模板 | Suggested Template\n\n' + + '您的PR主要包含 **' + suggestedTemplate + '** 相关的变更。\n\n' + + '**推荐模板 | Recommended Template:** `.github/PULL_REQUEST_TEMPLATE/' + suggestedTemplate + '.md`\n\n' + + '**如何使用 | How to use:** [点击查看模板内容](' + templateUrl + ')'; - _这是一个自动建议,您可以继续使用当前模板。_ + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: fallbackComment + }); + } + } else { + console.log('PR body has content, sending suggestion only'); - _This is an automated suggestion. You may continue using the current template._`; + let fileStats = []; + if (goFiles > 0) fileStats.push('- 🔧 Go files: ' + goFiles); + if (jsFiles > 0) fileStats.push('- 🎨 JavaScript files: ' + jsFiles); + if (tsFiles > 0) fileStats.push('- 🎨 TypeScript files: ' + tsFiles); + if (mdFiles > 0) fileStats.push('- 📝 Markdown files: ' + mdFiles); + if (otherFiles > 0) fileStats.push('- 📦 Other files: ' + otherFiles); + const fileStatsText = fileStats.join('\n'); - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number, - body: comment - }); + const templateUrl = 'https://raw.githubusercontent.com/' + context.repo.owner + '/' + context.repo.repo + '/dev/.github/PULL_REQUEST_TEMPLATE/' + suggestedTemplate + '.md'; - console.log(`Suggested ${suggestedTemplate} template`); + const comment = '## ' + templateEmoji + ' 建议使用专用模板 | Suggested Template\n\n' + + '您的PR主要包含 **' + suggestedTemplate + '** 相关的变更。我们建议使用更适合的模板以简化填写。\n\n' + + 'Your PR primarily contains **' + suggestedTemplate + '** changes. We suggest using a more suitable template to simplify filling.\n\n' + + '**文件统计 | File Statistics**\n' + fileStatsText + '\n\n' + + '**推荐模板 | Recommended Template**\n```\n.github/PULL_REQUEST_TEMPLATE/' + suggestedTemplate + '.md\n```\n\n' + + '**如何使用 | How to use**\n' + + '1. 编辑PR描述 | Edit PR description\n' + + '2. 复制 [' + suggestedTemplate + ' 模板内容](' + templateUrl + ') | Copy [' + suggestedTemplate + ' template content](' + templateUrl + ')\n' + + '3. 或在创建PR时使用URL参数 | Or use URL parameter when creating PR\n' + + ' `?template=' + suggestedTemplate + '.md`\n\n' + + '_这是一个自动建议,您可以继续使用当前模板。_\n\n' + + '_This is an automated suggestion. You may continue using the current template._'; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: comment + }); + } } else if (suggestedTemplate && !usingDefaultTemplate) { - console.log(`PR already uses a specific template`); + console.log('PR already uses a specific template'); } else { console.log('No specific template suggestion needed - mixed changes'); }