# Auto Label Workflow
# Automatically labels PRs based on file paths and patterns
# Location: .github/workflows/auto-label.yml
# Uses config from: .github/labeler.yml
name: Auto Label PRs
on:
# Trigger on PR events
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review]
# Also allow manual trigger for testing
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to label (optional)'
required: false
type: string
# Minimal permissions needed
permissions:
contents: read
pull-requests: write
issues: write # Needed for labeling issues if referenced
jobs:
label:
name: Auto-label PR
runs-on: ubuntu-latest
# Don't run on draft PRs unless they're marked ready
if: github.event.pull_request.draft != true || github.event.action == 'ready_for_review'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
# Need full history to properly detect changes
fetch-depth: 0
# Main labeling action
- name: Apply labels based on file paths
uses: actions/labeler@v5
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
configuration-path: .github/labeler.yml
sync-labels: true # Remove labels that no longer apply
# Add labels based on PR title (conventional commits)
- name: Label based on PR title
uses: bcoe/conventional-release-labels@v1
if: github.event_name == 'pull_request_target'
with:
type_labels: |
{
"feat": "feature",
"fix": "bug",
"docs": "documentation",
"style": "style",
"refactor": "refactor",
"perf": "performance",
"test": "test",
"build": "build",
"ci": "ci",
"chore": "chore",
"revert": "revert",
"breaking": "breaking"
}
# Skip if title doesn't match conventional format
ignored_types: '[]'
# Add size labels based on diff size
- name: Add size labels
id: size # FIXED: Added ID so we can reference outputs
uses: codelytv/pr-size-labeler@v1
if: github.event_name == 'pull_request_target'
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
xs_label: 'size: XS'
xs_max_size: 10
s_label: 'size: S'
s_max_size: 50
m_label: 'size: M'
m_max_size: 200
l_label: 'size: L'
l_max_size: 500
xl_label: 'size: XL'
fail_if_xl: false
message_if_xl: |
This PR is very large (500+ lines).
Consider breaking it into smaller, focused PRs for easier review.
files_to_ignore: |
'*.lock'
'*.sum'
'package-lock.json'
'poetry.lock'
'CHANGELOG.md'
# Add review labels based on PR characteristics
- name: Determine review requirements
if: github.event_name == 'pull_request_target'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Add labels based on PR characteristics
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'breaking') }}" == "true" ]]; then
echo "Adding needs-2-reviews label for breaking change"
gh pr edit ${{ github.event.pull_request.number }} --add-label "needs-2-reviews"
fi
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'security') }}" == "true" ]]; then
echo "Adding security-review label"
gh pr edit ${{ github.event.pull_request.number }} --add-label "security-review"
fi
# Check if it's a large PR (if size labeler added XL label)
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'size: XL') }}" == "true" ]]; then
echo "Large PR detected, may need additional review"
gh pr edit ${{ github.event.pull_request.number }} --add-label "needs-careful-review"
fi
continue-on-error: true
# Comment on PR with label summary (only on first labeling)
- name: Comment label summary
if: github.event.action == 'opened'
uses: actions/github-script@v7
with:
script: |
const labels = await github.rest.issues.listLabelsOnIssue({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number
});
if (labels.data.length > 0) {
const labelNames = labels.data.map(l => `\`${l.name}\``).join(', ');
const body = `🏷️ **Auto-labeling complete!**\n\nApplied labels: ${labelNames}\n\n` +
`Labels help us categorize and prioritize PRs. ` +
`You can manually add or remove labels as needed.`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
}
continue-on-error: true
# Manual workflow dispatch handling
- name: Label manually specified PR
if: github.event_name == 'workflow_dispatch' && github.event.inputs.pr_number != ''
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "Labeling PR #${{ github.event.inputs.pr_number }}"
gh pr edit ${{ github.event.inputs.pr_number }} --add-label "manually-labeled"