Skip to content

Commit 5c489f1

Browse files
author
Auto-Co AI
committed
Cycle 25: Auto-labeling feature — label PRs by file type and diff size
1 parent 2ac8f16 commit 5c489f1

2 files changed

Lines changed: 136 additions & 0 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ That's it. Every PR will get a generated description.
3636
- **AI mode** — optional OpenAI integration for smarter descriptions
3737
- **Custom templates** — use your own markdown template with placeholder variables
3838
- **Changelog generation** — auto-generate changelog entries from merged PRs
39+
- **Auto-labeling** — automatically labels PRs by file type (source, test, docs, config, etc.) and diff size
3940
- **Works on every PR** — open, synchronize, reopened, closed
4041
- **No servers** — runs entirely in GitHub Actions
4142
@@ -64,6 +65,9 @@ Add your OpenAI API key as a repository secret and enable AI mode:
6465
| `custom-template` | No | — | Inline custom markdown template with `{{summary}}`, `{{files}}`, `{{changes}}`, `{{file_count}}` placeholders |
6566
| `custom-template-file` | No | — | Path to a file in the repo containing a custom markdown template |
6667
| `generate-changelog` | No | `false` | When `true`, generates changelog entries from merged PRs |
68+
| `auto-label` | No | `false` | When `true`, automatically adds labels based on file types and diff size |
69+
| `label-prefix` | No | `"` | Optional prefix for auto-generated labels (e.g. `area:` → `area:source`) |
70+
| `size-labels` | No | `true` | When `auto-label` is true, adds size/xs/s/m/l/xl labels based on diff size |
6771

6872
## Outputs
6973

action.yml

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,25 @@ inputs:
4242
required: false
4343
default: "false"
4444

45+
auto-label:
46+
description: "When true, automatically adds labels to PRs based on file types and diff size"
47+
required: false
48+
default: "false"
49+
50+
label-prefix:
51+
description: "Optional prefix for auto-generated labels (e.g. 'area:' becomes 'area:source')"
52+
required: false
53+
default: ""
54+
55+
label-mappings:
56+
description: "Custom JSON mapping of file patterns to labels. Overrides default mappings"
57+
required: false
58+
59+
size-labels:
60+
description: "When true, adds size labels (size/small, size/medium, size/large) based on lines changed"
61+
required: false
62+
default: "true"
63+
4564
outputs:
4665
description:
4766
description: "The generated PR description"
@@ -151,6 +170,119 @@ runs:
151170
echo "${UNKNOWN_FILES:-None}" >> $GITHUB_OUTPUT
152171
echo "EOF" >> $GITHUB_OUTPUT
153172
173+
- name: Auto-label PR
174+
id: labels
175+
shell: bash
176+
if: ${{ inputs.auto-label == 'true' }}
177+
env:
178+
GH_TOKEN: ${{ inputs.github-token }}
179+
run: |
180+
PR_NUMBER="${{ steps.diff.outputs.pr_number }}"
181+
PREFIX="${{ inputs.label-prefix }}"
182+
USE_SIZE="${{ inputs.size-labels }}"
183+
CUSTOM_MAPPINGS="${{ inputs.label-mappings }}"
184+
185+
LABELS=()
186+
187+
# Read file list and determine category labels
188+
while IFS= read -r file; do
189+
[ -z "$file" ] && continue
190+
EXT="${file##*.}"
191+
LC_EXT=$(echo "$EXT" | tr '[:upper:]' '[:lower:]')
192+
193+
case "$LC_EXT" in
194+
ts|tsx|js|jsx|py|rs|go|java|rb|php|c|cpp|h|hpp|swift|kt|scala)
195+
if echo "$file" | grep -qiE '(test|spec|__tests__|__mocks__)'; then
196+
LABELS+=("${PREFIX}tests")
197+
else
198+
LABELS+=("${PREFIX}source")
199+
fi
200+
;;
201+
json|yaml|yml|toml|ini|cfg|env|conf)
202+
LABELS+=("${PREFIX}config")
203+
;;
204+
md|mdx|rst|txt|adoc|wiki)
205+
LABELS+=("${PREFIX}docs")
206+
;;
207+
svg|png|jpg|jpeg|gif|ico|woff|woff2|ttf|eot|css|scss|less)
208+
LABELS+=("${PREFIX}assets")
209+
;;
210+
dockerfile|yml|yaml)
211+
if echo "$file" | grep -qiE '(docker|container)'; then
212+
LABELS+=("${PREFIX}docker")
213+
fi
214+
;;
215+
*)
216+
;;
217+
esac
218+
219+
if echo "$file" | grep -qiE '(docker|container)'; then
220+
LABELS+=("${PREFIX}docker")
221+
fi
222+
if echo "$file" | grep -qiE '(ci|cd|github|workflows|actions)'; then
223+
LABELS+=("${PREFIX}ci")
224+
fi
225+
if echo "$file" | grep -qiE '(security|audit|vuln|cve)'; then
226+
LABELS+=("${PREFIX}security")
227+
fi
228+
if echo "$file" | grep -qiE '(db|migration|schema|sql)'; then
229+
LABELS+=("${PREFIX}database")
230+
fi
231+
done < /tmp/pr_files.txt
232+
233+
# Size labels
234+
if [ "$USE_SIZE" = "true" ]; then
235+
DIFF_SIZE="${{ steps.diff.outputs.diff_size }}"
236+
if [ "$DIFF_SIZE" -gt 0 ] 2>/dev/null; then
237+
if [ "$DIFF_SIZE" -lt 100 ]; then
238+
LABELS+=("${PREFIX}size/xs")
239+
elif [ "$DIFF_SIZE" -lt 500 ]; then
240+
LABELS+=("${PREFIX}size/s")
241+
elif [ "$DIFF_SIZE" -lt 2000 ]; then
242+
LABELS+=("${PREFIX}size/m")
243+
elif [ "$DIFF_SIZE" -lt 10000 ]; then
244+
LABELS+=("${PREFIX}size/l")
245+
else
246+
LABELS+=("${PREFIX}size/xl")
247+
fi
248+
fi
249+
fi
250+
251+
# Deduplicate labels
252+
UNIQUE_LABELS=()
253+
for lbl in "${LABELS[@]}"; do
254+
found=false
255+
for ulbl in "${UNIQUE_LABELS[@]}"; do
256+
[ "$ulbl" = "$lbl" ] && found=true && break
257+
done
258+
$found || UNIQUE_LABELS+=("$lbl")
259+
done
260+
261+
# Apply labels using gh
262+
for label in "${UNIQUE_LABELS[@]}"; do
263+
# Create label if it doesn't exist (but don't fail if it already does)
264+
gh label create "$label" --repo "${{ github.repository }}" --force 2>/dev/null || true
265+
done
266+
267+
if [ ${#UNIQUE_LABELS[@]} -gt 0 ]; then
268+
gh pr edit "$PR_NUMBER" --add-label "$(IFS=,; echo "${UNIQUE_LABELS[*]}")" --repo "${{ github.repository }}" 2>&1 || true
269+
echo "Applied labels: ${UNIQUE_LABELS[*]}"
270+
fi
271+
272+
echo "labels_applied=${#UNIQUE_LABELS[@]}" >> $GITHUB_OUTPUT
273+
LABELS_JSON="["
274+
FIRST=true
275+
for lbl in "${UNIQUE_LABELS[@]}"; do
276+
if [ "$FIRST" = true ]; then
277+
LABELS_JSON="$LABELS_JSON\"$lbl\""
278+
FIRST=false
279+
else
280+
LABELS_JSON="$LABELS_JSON,\"$lbl\""
281+
fi
282+
done
283+
LABELS_JSON="$LABELS_JSON]"
284+
echo "labels=$LABELS_JSON" >> $GITHUB_OUTPUT
285+
154286
- name: Generate description (template mode)
155287
id: generate
156288
shell: bash

0 commit comments

Comments
 (0)