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: Auto-label issues with AI | |
| on: | |
| issues: | |
| types: [opened] | |
| permissions: | |
| issues: write | |
| models: read | |
| jobs: | |
| label-issue: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Get AI label suggestions | |
| id: ai | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const issue = context.payload.issue; | |
| const title = issue.title; | |
| const body = issue.body || '(no description)'; | |
| const prompt = `Analyze this GitHub issue and return ONLY comma-separated numbers for applicable labels. | |
| Available labels: | |
| 1. Documentation - Issues or improvements related to documentation | |
| 2. Duplicate - This issue already exists | |
| 3. Enhancement - Improvement to existing functionality | |
| 4. good first issue - Good for newcomers | |
| 5. help wanted - Extra attention is needed | |
| 6. invalid - This doesn't seem right | |
| 7. question - Further information is requested | |
| 8. wontfix - This will not be worked on | |
| 9. ⊘ CRITICAL - Critical priority issue | |
| 13. ➥ Feature Request - Request for new functionality | |
| 16. 𓆣 Bug - Something isn't working | |
| 18. ꕤ DEV - Developer-created notes/issues for tracking progress, project planning, and development state | |
| Issue Title: ${title} | |
| Issue Body: ${body} | |
| Return ONLY the numbers, comma-separated. Examples: | |
| - For a bug report: 16 | |
| - For a feature request: 13 | |
| - For a critical bug: 16,9 | |
| - For a docs improvement: 1,3 | |
| - For a simple bug good for beginners: 16,4,5 | |
| - For a developer note / project tracking issue: 18 | |
| - If unclear/invalid: 6 or 7 | |
| NOTE: You can combine and mix various labels, but do not add any labels that are not listed above. | |
| Your response (numbers only):`; | |
| // Call GitHub Models API | |
| const response = await fetch('https://models.inference.ai.azure.com/chat/completions', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'Authorization': `Bearer ${process.env.GITHUB_TOKEN}` | |
| }, | |
| body: JSON.stringify({ | |
| model: 'DeepSeek-V3-0324', | |
| messages: [ | |
| { role: 'system', content: 'You are a GitHub issue classifier. Return ONLY comma-separated numbers, nothing else.' }, | |
| { role: 'user', content: prompt } | |
| ], | |
| max_tokens: 50, | |
| temperature: 0.1 | |
| }) | |
| }); | |
| if (!response.ok) { | |
| const error = await response.text(); | |
| core.setFailed(`API request failed: ${response.status} - ${error}`); | |
| return; | |
| } | |
| const data = await response.json(); | |
| const aiResponse = data.choices[0].message.content.trim(); | |
| core.info(`AI response: ${aiResponse}`); | |
| core.setOutput('labels', aiResponse); | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| - name: Apply labels | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const labelMap = { | |
| '1': 'Documentation', | |
| '2': 'Duplicate', | |
| '3': 'Enhancement', | |
| '4': 'good first issue', | |
| '5': 'help wanted', | |
| '6': 'invalid', | |
| '7': 'question', | |
| '8': 'wontfix', | |
| '9': '⊘ CRITICAL', | |
| '10': '⚲ Planned', | |
| '11': '✓ Resolved', | |
| '12': '✗ Cancelled', | |
| '13': '➥ Feature Request', | |
| '14': '⦻ Confirmed', | |
| '15': '⧖ In Progress', | |
| '16': '𓆣 Bug', | |
| '17': '𖦏 Investigating', | |
| '18': 'ꕤ DEV' | |
| }; | |
| const aiLabels = '${{ steps.ai.outputs.labels }}'; | |
| const numbers = aiLabels.match(/\d+/g) || []; | |
| // Always add Needs Triage, plus any AI-suggested labels | |
| const labelsToAdd = ['➤ Needs Triage']; | |
| for (const num of numbers) { | |
| if (labelMap[num]) { | |
| labelsToAdd.push(labelMap[num]); | |
| } | |
| } | |
| // Remove duplicates | |
| const uniqueLabels = [...new Set(labelsToAdd)]; | |
| core.info(`Applying labels: ${uniqueLabels.join(', ')}`); | |
| await github.rest.issues.addLabels({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.payload.issue.number, | |
| labels: uniqueLabels | |
| }); |